From 33cbd892127400d4a816b012f2bb98a7b9576e28 Mon Sep 17 00:00:00 2001 From: nextime Date: Sun, 17 Mar 2013 00:45:21 +0100 Subject: [PATCH] Migrate svn to git --- AUTHORS | 10 + BUGS | 1 + COPYING | 340 + ChangeLog | 1 + INSTALL | 185 + Makefile.am | 32 + Makefile.in | 880 + NEWS | 1 + README | 5 + TODO | 2 + acinclude.m4 | 74 + aclocal.m4 | 984 + config.h.in | 450 + configure | 11153 ++++++++ configure.ac | 399 + db/Makefile.am | 44 + db/Makefile.in | 439 + db/zm_create.sql | 934 + db/zm_create.sql.in | 623 + db/zm_create.sql.in.orig | 621 + db/zm_update-0.0.1.sql | 62 + db/zm_update-0.9.10.sql | 15 + db/zm_update-0.9.11.sql | 11 + db/zm_update-0.9.12.sql | 26 + db/zm_update-0.9.13.sql | 28 + db/zm_update-0.9.15.sql | 57 + db/zm_update-0.9.16.sql | 15 + db/zm_update-0.9.7.sql | 9 + db/zm_update-0.9.8.sql | 8 + db/zm_update-0.9.9.sql | 15 + db/zm_update-1.17.1.sql | 17 + db/zm_update-1.17.2.sql | 18 + db/zm_update-1.18.0.sql | 3 + db/zm_update-1.18.1.sql | 22 + db/zm_update-1.19.0.sql | 3 + db/zm_update-1.19.1.sql | 23 + db/zm_update-1.19.2.sql | 15 + db/zm_update-1.19.3.sql | 3 + db/zm_update-1.19.4.sql | 20 + db/zm_update-1.19.5.sql | 44 + db/zm_update-1.20.0.sql | 15 + db/zm_update-1.20.1.sql | 148 + db/zm_update-1.21.0.sql | 31 + db/zm_update-1.21.1.sql | 13 + db/zm_update-1.21.2.sql | 13 + db/zm_update-1.21.3.sql | 25 + db/zm_update-1.21.4.sql | 134 + db/zm_update-1.22.0.sql | 56 + db/zm_update-1.22.1.sql | 26 + db/zm_update-1.22.2.sql | 63 + db/zm_update-1.22.3.sql | 70 + db/zm_update-1.23.0.sql | 18 + db/zm_update-1.23.1.sql | 19 + db/zm_update-1.23.2.sql | 18 + db/zm_update-1.23.3.sql | 83 + db/zm_update-1.24.0.sql | 17 + db/zm_update-1.24.1.sql | 34 + db/zm_update-1.24.2.sql | 22 + db/zm_update-1.24.3.sql | 13 + db/zm_update-1.24.4.sql | 30 + db/zm_update-kfir-to-zum.sql | 24 + db/zm_update_1.25.0-to-zum.sql | 26 + depcomp | 423 + description-pak | 1 + doc-pak/AUTHORS | 6 + doc-pak/BUGS | 1 + doc-pak/COPYING | 340 + doc-pak/ChangeLog | 1 + doc-pak/INSTALL | 185 + doc-pak/NEWS | 1 + doc-pak/README | 5 + doc-pak/TODO | 2 + install-sh | 251 + misc/Makefile.am | 6 + misc/Makefile.in | 406 + misc/apache.conf | 39 + misc/apache.conf.in | 39 + misc/logrotate.conf | 19 + misc/logrotate.conf.in | 19 + misc/syslog.conf | 19 + misc/syslog.conf.in | 19 + missing | 336 + mkinstalldirs | 40 + plugins/.sconsign.dblite | Bin 0 -> 44547 bytes plugins/libzm_plugin_anpr/Makefile | 60 + plugins/libzm_plugin_anpr/anpr_plugin.cpp | 250 + plugins/libzm_plugin_anpr/anpr_plugin.h | 89 + plugins/libzm_plugin_anpr/plugin.conf | 8 + .../libzm_plugin_face_haar/.sconsign.dblite | Bin 0 -> 28235 bytes plugins/libzm_plugin_face_haar/SConstruct | 78 + .../data/haarcascade_frontalface_alt2.xml | 23550 ++++++++++++++++ .../libzm_plugin_face_haar/data/plugins.conf | 14 + .../debug/face_detector_plugin.os | Bin 0 -> 1777048 bytes .../libzm_plugin_face_haar.so | Bin 0 -> 717305 bytes .../release/face_detector_plugin.os | Bin 0 -> 574696 bytes .../src/face_detector_plugin.cpp | 400 + .../src/face_detector_plugin.h | 102 + scripts/Makefile.am | 75 + scripts/Makefile.in | 778 + scripts/ZoneMinder/Changes | 6 + scripts/ZoneMinder/MANIFEST | 7 + scripts/ZoneMinder/META.yml | 10 + scripts/ZoneMinder/MYMETA.yml | 22 + scripts/ZoneMinder/Makefile.PL | 41 + scripts/ZoneMinder/Makefile.old | 965 + scripts/ZoneMinder/README | 40 + scripts/ZoneMinder/blib/arch/.exists | 0 .../blib/arch/auto/ZoneMinder/.exists | 0 scripts/ZoneMinder/blib/bin/.exists | 0 scripts/ZoneMinder/blib/lib/.exists | 0 scripts/ZoneMinder/blib/lib/ZoneMinder.pm | 130 + .../ZoneMinder/blib/lib/ZoneMinder/Base.pm | 86 + .../ZoneMinder/blib/lib/ZoneMinder/Config.pm | 145 + .../blib/lib/ZoneMinder/ConfigAdmin.pm | 213 + .../blib/lib/ZoneMinder/ConfigData.pm | 2056 ++ .../ZoneMinder/blib/lib/ZoneMinder/Control.pm | 205 + .../blib/lib/ZoneMinder/Control/AxisV2.pm | 475 + .../blib/lib/ZoneMinder/Control/Ncs370.pm | 241 + .../lib/ZoneMinder/Control/PanasonicIP.pm | 322 + .../blib/lib/ZoneMinder/Control/PelcoD.pm | 735 + .../blib/lib/ZoneMinder/Control/Visca.pm | 668 + .../lib/ZoneMinder/Control/mjpgStreamer.pm | 252 + .../blib/lib/ZoneMinder/Database.pm | 238 + .../ZoneMinder/blib/lib/ZoneMinder/General.pm | 768 + .../ZoneMinder/blib/lib/ZoneMinder/Logger.pm | 861 + .../ZoneMinder/blib/lib/ZoneMinder/Memory.pm | 873 + .../blib/lib/ZoneMinder/Memory/Mapped.pm | 169 + .../blib/lib/ZoneMinder/Memory/Shared.pm | 161 + .../blib/lib/ZoneMinder/Trigger/Channel.pm | 166 + .../lib/ZoneMinder/Trigger/Channel/File.pm | 121 + .../lib/ZoneMinder/Trigger/Channel/Handle.pm | 154 + .../lib/ZoneMinder/Trigger/Channel/Inet.pm | 142 + .../lib/ZoneMinder/Trigger/Channel/Serial.pm | 160 + .../ZoneMinder/Trigger/Channel/Spawning.pm | 112 + .../lib/ZoneMinder/Trigger/Channel/Unix.pm | 141 + .../blib/lib/ZoneMinder/Trigger/Connection.pm | 239 + .../ZoneMinder/Trigger/Connection/Example.pm | 134 + .../blib/lib/auto/ZoneMinder/.exists | 0 scripts/ZoneMinder/blib/man1/.exists | 0 scripts/ZoneMinder/blib/man3/.exists | 0 scripts/ZoneMinder/blib/man3/ZoneMinder.3pm | 177 + .../ZoneMinder/blib/man3/ZoneMinder::Base.3pm | 157 + .../blib/man3/ZoneMinder::Config.3pm | 166 + .../blib/man3/ZoneMinder::ConfigAdmin.3pm | 180 + .../blib/man3/ZoneMinder::ConfigData.3pm | 180 + .../blib/man3/ZoneMinder::Control.3pm | 169 + .../blib/man3/ZoneMinder::Control::AxisV2.3pm | 169 + .../blib/man3/ZoneMinder::Control::Ncs370.3pm | 169 + .../man3/ZoneMinder::Control::PanasonicIP.3pm | 169 + .../blib/man3/ZoneMinder::Control::PelcoD.3pm | 169 + .../blib/man3/ZoneMinder::Control::Visca.3pm | 169 + .../ZoneMinder::Control::mjpgStreamer.3pm | 169 + .../blib/man3/ZoneMinder::Database.3pm | 169 + .../blib/man3/ZoneMinder::General.3pm | 169 + .../blib/man3/ZoneMinder::Logger.3pm | 259 + .../blib/man3/ZoneMinder::Memory.3pm | 313 + .../man3/ZoneMinder::Trigger::Channel.3pm | 169 + .../ZoneMinder::Trigger::Channel::File.3pm | 169 + .../ZoneMinder::Trigger::Channel::Handle.3pm | 169 + .../ZoneMinder::Trigger::Channel::Inet.3pm | 169 + .../ZoneMinder::Trigger::Channel::Serial.3pm | 169 + ...ZoneMinder::Trigger::Channel::Spawning.3pm | 169 + .../ZoneMinder::Trigger::Channel::Unix.3pm | 169 + .../man3/ZoneMinder::Trigger::Connection.3pm | 169 + ...neMinder::Trigger::Connection::Example.3pm | 169 + scripts/ZoneMinder/blib/script/.exists | 0 scripts/ZoneMinder/lib/ZoneMinder.pm | 130 + scripts/ZoneMinder/lib/ZoneMinder/Base.pm | 86 + scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in | 86 + scripts/ZoneMinder/lib/ZoneMinder/Config.pm | 145 + .../ZoneMinder/lib/ZoneMinder/Config.pm.in | 145 + .../ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm | 213 + .../ZoneMinder/lib/ZoneMinder/ConfigData.pm | 2056 ++ .../lib/ZoneMinder/ConfigData.pm.in | 2056 ++ .../lib/ZoneMinder/ConfigData.pm.in.orig | 2015 ++ scripts/ZoneMinder/lib/ZoneMinder/Control.pm | 205 + .../lib/ZoneMinder/Control/AxisV2.pm | 475 + .../lib/ZoneMinder/Control/Ncs370.pm | 241 + .../lib/ZoneMinder/Control/PanasonicIP.pm | 322 + .../lib/ZoneMinder/Control/PelcoD.pm | 735 + .../lib/ZoneMinder/Control/PelcoP.pm | 736 + .../lib/ZoneMinder/Control/Visca.pm | 668 + .../lib/ZoneMinder/Control/mjpgStreamer.pm | 252 + scripts/ZoneMinder/lib/ZoneMinder/Database.pm | 238 + scripts/ZoneMinder/lib/ZoneMinder/General.pm | 768 + scripts/ZoneMinder/lib/ZoneMinder/Logger.pm | 861 + scripts/ZoneMinder/lib/ZoneMinder/Memory.pm | 873 + .../ZoneMinder/lib/ZoneMinder/Memory.pm.in | 873 + .../lib/ZoneMinder/Memory/Mapped.pm | 169 + .../lib/ZoneMinder/Memory/Shared.pm | 161 + .../lib/ZoneMinder/Trigger/Channel.pm | 166 + .../lib/ZoneMinder/Trigger/Channel/File.pm | 121 + .../lib/ZoneMinder/Trigger/Channel/Handle.pm | 154 + .../lib/ZoneMinder/Trigger/Channel/Inet.pm | 142 + .../lib/ZoneMinder/Trigger/Channel/Serial.pm | 160 + .../ZoneMinder/Trigger/Channel/Spawning.pm | 112 + .../lib/ZoneMinder/Trigger/Channel/Unix.pm | 141 + .../lib/ZoneMinder/Trigger/Connection.pm | 239 + .../ZoneMinder/Trigger/Connection/Example.pm | 134 + scripts/ZoneMinder/pm_to_blib | 0 scripts/ZoneMinder/t/ZoneMinder.t | 17 + scripts/zm | 120 + scripts/zm.in | 120 + scripts/zmaudit.pl | 510 + scripts/zmaudit.pl.in | 510 + scripts/zmcontrol.pl | 237 + scripts/zmcontrol.pl.in | 237 + scripts/zmdbbackup | 37 + scripts/zmdbbackup.in | 37 + scripts/zmdbrestore | 172 + scripts/zmdbrestore.in | 172 + scripts/zmdc.pl | 798 + scripts/zmdc.pl.in | 798 + scripts/zmeventdump | 50 + scripts/zmeventdump.in | 50 + scripts/zmfilter.pl | 1169 + scripts/zmfilter.pl.in | 1169 + scripts/zmlogrotate.conf | 20 + scripts/zmlogrotate.conf.in | 20 + scripts/zmpkg.pl | 247 + scripts/zmpkg.pl.in | 247 + scripts/zmtrack.pl | 205 + scripts/zmtrack.pl.in | 205 + scripts/zmtrigger.pl | 440 + scripts/zmtrigger.pl.in | 440 + scripts/zmupdate.pl | 984 + scripts/zmupdate.pl.in | 984 + scripts/zmvideo.pl | 243 + scripts/zmvideo.pl.in | 243 + scripts/zmwatch.pl | 148 + scripts/zmwatch.pl.in | 148 + scripts/zmx10.pl | 675 + scripts/zmx10.pl.in | 675 + src/.deps/zm.Po | 269 + src/.deps/zm_box.Po | 297 + src/.deps/zm_buffer.Po | 275 + src/.deps/zm_camera.Po | 418 + src/.deps/zm_comms.Po | 439 + src/.deps/zm_config.Po | 310 + src/.deps/zm_coord.Po | 272 + src/.deps/zm_db.Po | 285 + src/.deps/zm_detector.Po | 548 + src/.deps/zm_event.Po | 758 + src/.deps/zm_exception.Po | 271 + src/.deps/zm_ffmpeg.Po | 1 + src/.deps/zm_ffmpeg_camera.Po | 516 + src/.deps/zm_file_camera.Po | 498 + src/.deps/zm_image.Po | 399 + src/.deps/zm_image_analyser.Po | 627 + src/.deps/zm_jpeg.Po | 295 + src/.deps/zm_local_camera.Po | 563 + src/.deps/zm_logger.Po | 370 + src/.deps/zm_monitor.Po | 813 + src/.deps/zm_mpeg.Po | 430 + src/.deps/zm_plugin.Po | 298 + src/.deps/zm_plugin_manager.Po | 655 + src/.deps/zm_poly.Po | 299 + src/.deps/zm_regexp.Po | 287 + src/.deps/zm_remote_camera.Po | 463 + src/.deps/zm_remote_camera_http.Po | 473 + src/.deps/zm_remote_camera_rtsp.Po | 582 + src/.deps/zm_rtp.Po | 271 + src/.deps/zm_rtp_ctrl.Po | 521 + src/.deps/zm_rtp_data.Po | 521 + src/.deps/zm_rtp_source.Po | 344 + src/.deps/zm_rtsp.Po | 547 + src/.deps/zm_sdp.Po | 453 + src/.deps/zm_signal.Po | 320 + src/.deps/zm_stream.Po | 692 + src/.deps/zm_thread.Po | 341 + src/.deps/zm_time.Po | 274 + src/.deps/zm_timer.Po | 300 + src/.deps/zm_user.Po | 342 + src/.deps/zm_utils.Po | 307 + src/.deps/zm_zone.Po | 693 + src/.deps/zma.Po | 718 + src/.deps/zmc.Po | 726 + src/.deps/zmf.Po | 722 + src/.deps/zmfix.Po | 347 + src/.deps/zms.Po | 754 + src/.deps/zmstreamer.Po | 753 + src/.deps/zmu.Po | 771 + src/Makefile.am | 141 + src/Makefile.in | 779 + src/jinclude.h | 91 + src/zm.cpp | 22 + src/zm.h | 35 + src/zm_box.cpp | 23 + src/zm_box.h | 70 + src/zm_buffer.cpp | 69 + src/zm_buffer.h | 214 + src/zm_camera.cpp | 52 + src/zm_camera.h | 81 + src/zm_comms.cpp | 711 + src/zm_comms.h | 889 + src/zm_config.cpp | 301 + src/zm_config.h | 135 + src/zm_config.h.in | 135 + src/zm_config_defines.h | 676 + src/zm_coord.cpp | 23 + src/zm_coord.h | 67 + src/zm_db.cpp | 66 + src/zm_db.h | 37 + src/zm_detector.cpp | 200 + src/zm_detector.h | 129 + src/zm_event.cpp | 1457 + src/zm_event.h | 266 + src/zm_exception.cpp | 22 + src/zm_exception.h | 68 + src/zm_ffmpeg.cpp | 24 + src/zm_ffmpeg.h | 74 + src/zm_ffmpeg_camera.cpp | 263 + src/zm_ffmpeg_camera.h | 69 + src/zm_file_camera.cpp | 91 + src/zm_file_camera.h | 51 + src/zm_font.h | 3337 +++ src/zm_image.cpp | 5463 ++++ src/zm_image.h | 308 + src/zm_image_analyser.cpp | 87 + src/zm_image_analyser.h | 65 + src/zm_jpeg.cpp | 466 + src/zm_jpeg.h | 50 + src/zm_local_camera.cpp | 2174 ++ src/zm_local_camera.h | 143 + src/zm_logger.cpp | 610 + src/zm_logger.h | 239 + src/zm_mem_utils.h | 161 + src/zm_monitor.cpp | 4232 +++ src/zm_monitor.cpp.orig | 3889 +++ src/zm_monitor.h | 477 + src/zm_monitor.h.orig | 458 + src/zm_mpeg.cpp | 486 + src/zm_mpeg.h | 70 + src/zm_plugin.cpp | 105 + src/zm_plugin.h | 78 + src/zm_plugin_manager.cpp | 118 + src/zm_plugin_manager.h | 85 + src/zm_poly.cpp | 118 + src/zm_poly.h | 125 + src/zm_regexp.cpp | 124 + src/zm_regexp.h | 65 + src/zm_remote_camera.cpp | 75 + src/zm_remote_camera.h | 65 + src/zm_remote_camera_http.cpp | 1150 + src/zm_remote_camera_http.h | 63 + src/zm_remote_camera_rtsp.cpp | 326 + src/zm_remote_camera_rtsp.h | 80 + src/zm_rgb.h | 157 + src/zm_rtp.cpp | 22 + src/zm_rtp.h | 27 + src/zm_rtp_ctrl.cpp | 344 + src/zm_rtp_ctrl.h | 157 + src/zm_rtp_data.cpp | 120 + src/zm_rtp_data.h | 67 + src/zm_rtp_source.cpp | 325 + src/zm_rtp_source.h | 179 + src/zm_rtsp.cpp | 719 + src/zm_rtsp.h | 129 + src/zm_sdp.cpp | 403 + src/zm_sdp.h | 241 + src/zm_signal.cpp | 197 + src/zm_signal.h | 52 + src/zm_stream.cpp | 318 + src/zm_stream.h | 178 + src/zm_thread.cpp | 340 + src/zm_thread.h | 227 + src/zm_threaddata.cpp | 22 + src/zm_time.cpp | 22 + src/zm_time.h | 209 + src/zm_timer.cpp | 119 + src/zm_timer.h | 87 + src/zm_user.cpp | 246 + src/zm_user.h | 74 + src/zm_utils.cpp | 253 + src/zm_utils.h | 54 + src/zm_zone.cpp | 1082 + src/zm_zone.cpp.orig | 1035 + src/zm_zone.h | 164 + src/zm_zone.h.orig | 153 + src/zma.cpp | 139 + src/zmc.cpp | 304 + src/zmf.cpp | 283 + src/zmf.h | 32 + src/zmfix.cpp | 205 + src/zms.cpp | 327 + src/zmstreamer.cpp | 195 + src/zmu.cpp | 751 + stamp-h.in | 1 + stamp-h1 | 1 + umutils/nextimeconfigure.zm | 16 + web/Makefile.am | 35 + web/Makefile.in | 685 + web/ajax/Makefile.am | 12 + web/ajax/Makefile.in | 459 + web/ajax/alarm.php | 42 + web/ajax/control.php | 64 + web/ajax/event.php | 124 + web/ajax/log.php | 363 + web/ajax/status.php | 413 + web/ajax/stream.php | 135 + web/ajax/zone.php | 45 + web/css/Makefile.am | 8 + web/css/Makefile.in | 455 + web/css/overlay.css | 49 + web/css/reset.css | 77 + web/css/spinner.css | 19 + web/graphics/Makefile.am | 8 + web/graphics/Makefile.in | 455 + web/graphics/favicon.ico | Bin 0 -> 318 bytes web/graphics/spinner.gif | Bin 0 -> 2545 bytes web/graphics/transparent.gif | Bin 0 -> 61 bytes web/includes/Makefile.am | 17 + web/includes/Makefile.in | 488 + web/includes/actions.php | 932 + web/includes/config.php | 173 + web/includes/config.php.in | 173 + web/includes/control_functions.php | 969 + web/includes/database.php | 350 + web/includes/functions.php | 2436 ++ web/includes/lang.php | 46 + web/includes/logger.php | 586 + web/index.php | 140 + web/js/Makefile.am | 8 + web/js/Makefile.in | 455 + web/js/logger.js | 116 + web/js/mootools.ext.js | 20 + web/js/overlay.js | 133 + web/lang/Makefile.am | 25 + web/lang/Makefile.in | 472 + web/lang/big5_big5.php | 853 + web/lang/big5_big5.php.orig | 850 + web/lang/cn_zh.php | 848 + web/lang/cn_zh.php.orig | 845 + web/lang/cs_cz.php | 849 + web/lang/cs_cz.php.orig | 846 + web/lang/de_de.php | 849 + web/lang/de_de.php.orig | 846 + web/lang/dk_dk.php | 850 + web/lang/dk_dk.php.orig | 847 + web/lang/en_gb.php | 850 + web/lang/en_gb.php.orig | 846 + web/lang/en_us.php | 81 + web/lang/es_ar.php | 702 + web/lang/es_ar.php.orig | 699 + web/lang/es_es.php | 747 + web/lang/et_ee.php | 842 + web/lang/fr_fr.php | 849 + web/lang/fr_fr.php.orig | 846 + web/lang/he_il.php | 849 + web/lang/he_il.php.orig | 846 + web/lang/hu_hu.php | 858 + web/lang/hu_hu.php.orig | 855 + web/lang/it_it.php | 854 + web/lang/it_it.php.orig | 851 + web/lang/ja_jp.php | 849 + web/lang/ja_jp.php.orig | 846 + web/lang/nl_nl.php | 850 + web/lang/nl_nl.php.orig | 846 + web/lang/pl_pl.php | 828 + web/lang/pl_pl.php.orig | 825 + web/lang/pt_br.php | 789 + web/lang/pt_br.php.orig | 786 + web/lang/ro_ro.php | 1283 + web/lang/ro_ro.php.orig | 1280 + web/lang/ru_ru.php | 848 + web/lang/ru_ru.php.orig | 845 + web/lang/se_se.php | 849 + web/lang/se_se.php.orig | 846 + web/lang/updateLangs.php | 122 + web/scripts/retag.sh | 28 + web/scripts/swap.pl | 63 + web/skins/Makefile.am | 6 + web/skins/Makefile.in | 597 + web/skins/classic/Makefile.am | 15 + web/skins/classic/Makefile.in | 661 + web/skins/classic/ajax/Makefile.am | 5 + web/skins/classic/ajax/Makefile.in | 451 + web/skins/classic/css/Makefile.am | 8 + web/skins/classic/css/Makefile.in | 455 + web/skins/classic/css/control.css | 147 + web/skins/classic/css/export.css | 54 + web/skins/classic/css/skin.css | 439 + web/skins/classic/graphics/Makefile.am | 23 + web/skins/classic/graphics/Makefile.in | 470 + web/skins/classic/graphics/arrow-d.gif | Bin 0 -> 293 bytes web/skins/classic/graphics/arrow-dl.gif | Bin 0 -> 232 bytes web/skins/classic/graphics/arrow-dr.gif | Bin 0 -> 263 bytes web/skins/classic/graphics/arrow-l-d.gif | Bin 0 -> 538 bytes web/skins/classic/graphics/arrow-l-u.gif | Bin 0 -> 524 bytes web/skins/classic/graphics/arrow-l.gif | Bin 0 -> 284 bytes web/skins/classic/graphics/arrow-r.gif | Bin 0 -> 265 bytes web/skins/classic/graphics/arrow-s-d.gif | Bin 0 -> 206 bytes web/skins/classic/graphics/arrow-s-u.gif | Bin 0 -> 203 bytes web/skins/classic/graphics/arrow-u.gif | Bin 0 -> 278 bytes web/skins/classic/graphics/arrow-ul.gif | Bin 0 -> 286 bytes web/skins/classic/graphics/arrow-ur.gif | Bin 0 -> 282 bytes web/skins/classic/graphics/center.gif | Bin 0 -> 621 bytes web/skins/classic/graphics/point-g.gif | Bin 0 -> 76 bytes web/skins/classic/graphics/point-o.gif | Bin 0 -> 76 bytes web/skins/classic/graphics/point-r.gif | Bin 0 -> 76 bytes web/skins/classic/graphics/seq-d.gif | Bin 0 -> 68 bytes web/skins/classic/graphics/seq-u.gif | Bin 0 -> 68 bytes web/skins/classic/includes/Makefile.am | 11 + web/skins/classic/includes/Makefile.in | 458 + web/skins/classic/includes/config.php | 112 + .../classic/includes/control_functions.php | 390 + .../classic/includes/export_functions.php | 1140 + web/skins/classic/includes/functions.php | 112 + web/skins/classic/includes/init.php | 0 .../classic/includes/timeline_functions.php | 524 + web/skins/classic/js/Makefile.am | 7 + web/skins/classic/js/Makefile.in | 454 + web/skins/classic/js/skin.js | 289 + web/skins/classic/js/skin.js.php | 40 + web/skins/classic/lang/Makefile.am | 5 + web/skins/classic/lang/Makefile.in | 451 + web/skins/classic/skin.php | 73 + web/skins/classic/svn-commit.tmp | 5 + web/skins/classic/views/Makefile.am | 55 + web/skins/classic/views/Makefile.in | 701 + web/skins/classic/views/bandwidth.php | 58 + web/skins/classic/views/blank.php | 37 + web/skins/classic/views/console.php | 342 + web/skins/classic/views/control.php | 81 + web/skins/classic/views/controlcap.php | 512 + web/skins/classic/views/controlcaps.php | 90 + web/skins/classic/views/controlpreset.php | 72 + web/skins/classic/views/css/Makefile.am | 31 + web/skins/classic/views/css/Makefile.in | 478 + web/skins/classic/views/css/console.css | 97 + web/skins/classic/views/css/control.css | 1 + web/skins/classic/views/css/controlcaps.css | 3 + web/skins/classic/views/css/devices.css | 4 + web/skins/classic/views/css/event.css | 232 + web/skins/classic/views/css/events.css | 42 + web/skins/classic/views/css/export.css | 15 + web/skins/classic/views/css/filter.css | 25 + web/skins/classic/views/css/frame.css | 30 + web/skins/classic/views/css/frames.css | 15 + web/skins/classic/views/css/groups.css | 6 + web/skins/classic/views/css/log.css | 53 + web/skins/classic/views/css/monitor.css | 5 + web/skins/classic/views/css/montage.css | 41 + web/skins/classic/views/css/montage_2wide.css | 30 + web/skins/classic/views/css/montage_3wide.css | 37 + .../views/css/montage_3wide50enlarge.css | 74 + web/skins/classic/views/css/montage_4wide.css | 44 + .../classic/views/css/montage_freeform.css | 9 + web/skins/classic/views/css/options.css | 24 + web/skins/classic/views/css/plugin.css | 20 + web/skins/classic/views/css/stats.css | 9 + web/skins/classic/views/css/timeline.css | 222 + web/skins/classic/views/css/timeline.css.php | 77 + web/skins/classic/views/css/video.css | 19 + web/skins/classic/views/css/watch.css | 134 + web/skins/classic/views/css/zone.css | 91 + web/skins/classic/views/cycle.php | 129 + web/skins/classic/views/device.php | 71 + web/skins/classic/views/devices.php | 86 + web/skins/classic/views/donate.php | 65 + web/skins/classic/views/error.php | 43 + web/skins/classic/views/event.php | 222 + web/skins/classic/views/eventdetail.php | 134 + web/skins/classic/views/events.php | 270 + web/skins/classic/views/export.php | 131 + web/skins/classic/views/filter.php | 331 + web/skins/classic/views/filtersave.php | 86 + web/skins/classic/views/frame.php | 103 + web/skins/classic/views/frames.php | 103 + web/skins/classic/views/function.php | 64 + web/skins/classic/views/group.php | 88 + web/skins/classic/views/groups.php | 94 + web/skins/classic/views/js/Makefile.am | 49 + web/skins/classic/views/js/Makefile.in | 496 + web/skins/classic/views/js/console.js | 65 + web/skins/classic/views/js/console.js.php | 28 + web/skins/classic/views/js/control.js | 49 + web/skins/classic/views/js/controlpreset.js | 14 + .../classic/views/js/controlpreset.js.php | 9 + web/skins/classic/views/js/cycle.js | 11 + web/skins/classic/views/js/cycle.js.php | 5 + web/skins/classic/views/js/devices.js | 47 + web/skins/classic/views/js/donate.js | 14 + web/skins/classic/views/js/donate.js.php | 2 + web/skins/classic/views/js/event.js | 754 + web/skins/classic/views/js/event.js.php | 48 + web/skins/classic/views/js/events.js | 150 + web/skins/classic/views/js/events.js.php | 13 + web/skins/classic/views/js/export.js | 58 + web/skins/classic/views/js/export.js.php | 22 + web/skins/classic/views/js/filter.js | 120 + web/skins/classic/views/js/filter.js.php | 56 + web/skins/classic/views/js/group.js | 11 + web/skins/classic/views/js/groups.js | 47 + web/skins/classic/views/js/log.js | 314 + web/skins/classic/views/js/login.js | 1 + web/skins/classic/views/js/monitor.js | 56 + web/skins/classic/views/js/monitor.js.php | 187 + web/skins/classic/views/js/monitorpreset.js | 14 + web/skins/classic/views/js/monitorprobe.js | 14 + web/skins/classic/views/js/montage.js | 152 + web/skins/classic/views/js/montage.js.php | 37 + web/skins/classic/views/js/options.js.php | 5 + web/skins/classic/views/js/plugin.js | 29 + web/skins/classic/views/js/plugin.js.php | 0 web/skins/classic/views/js/postlogin.js | 1 + web/skins/classic/views/js/state.js | 43 + web/skins/classic/views/js/state.js.php | 2 + web/skins/classic/views/js/timeline.js | 137 + web/skins/classic/views/js/timeline.js.php | 16 + web/skins/classic/views/js/user.js | 36 + web/skins/classic/views/js/version.js | 18 + web/skins/classic/views/js/version.js.php | 1 + web/skins/classic/views/js/video.js | 38 + web/skins/classic/views/js/video.js.php | 5 + web/skins/classic/views/js/watch.js | 723 + web/skins/classic/views/js/watch.js.php | 75 + web/skins/classic/views/js/zone.js | 514 + web/skins/classic/views/js/zone.js.php | 66 + web/skins/classic/views/log.php | 115 + web/skins/classic/views/login.php | 49 + web/skins/classic/views/logout.php | 51 + web/skins/classic/views/monitor.php | 814 + web/skins/classic/views/monitor.php.orig | 806 + web/skins/classic/views/monitorpreset.php | 60 + web/skins/classic/views/monitorprobe.php | 333 + web/skins/classic/views/montage.php | 151 + web/skins/classic/views/none.php | 48 + web/skins/classic/views/optionhelp.php | 44 + web/skins/classic/views/options.php | 324 + web/skins/classic/views/plugin.php | 170 + web/skins/classic/views/postlogin.php | 33 + web/skins/classic/views/settings.php | 78 + web/skins/classic/views/state.php | 106 + web/skins/classic/views/stats.php | 111 + web/skins/classic/views/status.php | 85 + web/skins/classic/views/timeline.php | 974 + web/skins/classic/views/user.php | 154 + web/skins/classic/views/version.php | 93 + web/skins/classic/views/video.php | 241 + web/skins/classic/views/watch.php | 230 + web/skins/classic/views/zone.php | 288 + web/skins/classic/views/zones.php | 106 + web/skins/mobile/Makefile.am | 14 + web/skins/mobile/Makefile.in | 660 + web/skins/mobile/ajax/Makefile.am | 5 + web/skins/mobile/ajax/Makefile.in | 451 + web/skins/mobile/css/Makefile.am | 6 + web/skins/mobile/css/Makefile.in | 453 + web/skins/mobile/css/skin.css | 311 + web/skins/mobile/graphics/Makefile.am | 5 + web/skins/mobile/graphics/Makefile.in | 451 + web/skins/mobile/includes/Makefile.am | 9 + web/skins/mobile/includes/Makefile.in | 456 + web/skins/mobile/includes/config.php | 63 + .../mobile/includes/control_functions.php | 186 + web/skins/mobile/includes/functions.php | 66 + web/skins/mobile/includes/init.php | 29 + web/skins/mobile/lang/Makefile.am | 5 + web/skins/mobile/lang/Makefile.in | 451 + web/skins/mobile/skin.php | 104 + web/skins/mobile/views/Makefile.am | 22 + web/skins/mobile/views/Makefile.in | 668 + web/skins/mobile/views/console.php | 178 + web/skins/mobile/views/css/Makefile.am | 6 + web/skins/mobile/views/css/Makefile.in | 453 + web/skins/mobile/views/css/console.css | 16 + web/skins/mobile/views/devices.php | 73 + web/skins/mobile/views/error.php | 34 + web/skins/mobile/views/event.php | 143 + web/skins/mobile/views/eventdetails.php | 86 + web/skins/mobile/views/events.php | 157 + web/skins/mobile/views/filter.php | 71 + web/skins/mobile/views/frame.php | 73 + web/skins/mobile/views/function.php | 66 + web/skins/mobile/views/login.php | 54 + web/skins/mobile/views/montage.php | 75 + web/skins/mobile/views/state.php | 77 + web/skins/mobile/views/video.php | 226 + web/skins/mobile/views/watch.php | 154 + web/skins/xml/Makefile.am | 10 + web/skins/xml/Makefile.in | 656 + web/skins/xml/includes/Makefile.am | 8 + web/skins/xml/includes/Makefile.in | 455 + web/skins/xml/includes/config.php | 155 + web/skins/xml/includes/functions.php | 455 + web/skins/xml/includes/init.php | 2 + web/skins/xml/skin.php | 46 + web/skins/xml/views/Makefile.am | 11 + web/skins/xml/views/Makefile.in | 656 + web/skins/xml/views/actions.php | 393 + web/skins/xml/views/console.php | 259 + web/skins/xml/views/none.php | 0 web/skins/xml/views/notfound.png | Bin 0 -> 7332 bytes web/tools/Makefile.am | 4 + web/tools/Makefile.in | 595 + web/tools/mootools/Makefile.am | 18 + web/tools/mootools/Makefile.in | 468 + web/tools/mootools/mootools-core-1.3.2-nc.js | 5515 ++++ web/tools/mootools/mootools-core-1.3.2-yc.js | 450 + .../mootools/mootools-more-1.3.2.1-nc.js | 10042 +++++++ .../mootools/mootools-more-1.3.2.1-yc.js | 742 + web/views/Makefile.am | 6 + web/views/Makefile.in | 453 + web/views/file.php | 56 + web/views/image.php | 102 + zm.conf.in | 50 + zmconfgen.pl.in | 190 + 708 files changed, 249852 insertions(+) create mode 100644 AUTHORS create mode 100644 BUGS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.in create mode 100644 NEWS create mode 100644 README create mode 100644 TODO create mode 100644 acinclude.m4 create mode 100644 aclocal.m4 create mode 100644 config.h.in create mode 100755 configure create mode 100644 configure.ac create mode 100644 db/Makefile.am create mode 100644 db/Makefile.in create mode 100644 db/zm_create.sql create mode 100644 db/zm_create.sql.in create mode 100644 db/zm_create.sql.in.orig create mode 100644 db/zm_update-0.0.1.sql create mode 100644 db/zm_update-0.9.10.sql create mode 100644 db/zm_update-0.9.11.sql create mode 100644 db/zm_update-0.9.12.sql create mode 100644 db/zm_update-0.9.13.sql create mode 100644 db/zm_update-0.9.15.sql create mode 100644 db/zm_update-0.9.16.sql create mode 100644 db/zm_update-0.9.7.sql create mode 100644 db/zm_update-0.9.8.sql create mode 100644 db/zm_update-0.9.9.sql create mode 100644 db/zm_update-1.17.1.sql create mode 100644 db/zm_update-1.17.2.sql create mode 100644 db/zm_update-1.18.0.sql create mode 100644 db/zm_update-1.18.1.sql create mode 100644 db/zm_update-1.19.0.sql create mode 100644 db/zm_update-1.19.1.sql create mode 100644 db/zm_update-1.19.2.sql create mode 100644 db/zm_update-1.19.3.sql create mode 100644 db/zm_update-1.19.4.sql create mode 100644 db/zm_update-1.19.5.sql create mode 100644 db/zm_update-1.20.0.sql create mode 100644 db/zm_update-1.20.1.sql create mode 100644 db/zm_update-1.21.0.sql create mode 100644 db/zm_update-1.21.1.sql create mode 100644 db/zm_update-1.21.2.sql create mode 100644 db/zm_update-1.21.3.sql create mode 100644 db/zm_update-1.21.4.sql create mode 100644 db/zm_update-1.22.0.sql create mode 100644 db/zm_update-1.22.1.sql create mode 100644 db/zm_update-1.22.2.sql create mode 100644 db/zm_update-1.22.3.sql create mode 100644 db/zm_update-1.23.0.sql create mode 100644 db/zm_update-1.23.1.sql create mode 100644 db/zm_update-1.23.2.sql create mode 100644 db/zm_update-1.23.3.sql create mode 100644 db/zm_update-1.24.0.sql create mode 100644 db/zm_update-1.24.1.sql create mode 100644 db/zm_update-1.24.2.sql create mode 100644 db/zm_update-1.24.3.sql create mode 100644 db/zm_update-1.24.4.sql create mode 100644 db/zm_update-kfir-to-zum.sql create mode 100644 db/zm_update_1.25.0-to-zum.sql create mode 100755 depcomp create mode 100644 description-pak create mode 100644 doc-pak/AUTHORS create mode 100644 doc-pak/BUGS create mode 100644 doc-pak/COPYING create mode 100644 doc-pak/ChangeLog create mode 100644 doc-pak/INSTALL create mode 100644 doc-pak/NEWS create mode 100644 doc-pak/README create mode 100644 doc-pak/TODO create mode 100755 install-sh create mode 100644 misc/Makefile.am create mode 100644 misc/Makefile.in create mode 100644 misc/apache.conf create mode 100644 misc/apache.conf.in create mode 100644 misc/logrotate.conf create mode 100644 misc/logrotate.conf.in create mode 100644 misc/syslog.conf create mode 100644 misc/syslog.conf.in create mode 100755 missing create mode 100755 mkinstalldirs create mode 100644 plugins/.sconsign.dblite create mode 100644 plugins/libzm_plugin_anpr/Makefile create mode 100644 plugins/libzm_plugin_anpr/anpr_plugin.cpp create mode 100644 plugins/libzm_plugin_anpr/anpr_plugin.h create mode 100644 plugins/libzm_plugin_anpr/plugin.conf create mode 100644 plugins/libzm_plugin_face_haar/.sconsign.dblite create mode 100644 plugins/libzm_plugin_face_haar/SConstruct create mode 100644 plugins/libzm_plugin_face_haar/data/haarcascade_frontalface_alt2.xml create mode 100644 plugins/libzm_plugin_face_haar/data/plugins.conf create mode 100644 plugins/libzm_plugin_face_haar/debug/face_detector_plugin.os create mode 100755 plugins/libzm_plugin_face_haar/libzm_plugin_face_haar.so create mode 100644 plugins/libzm_plugin_face_haar/release/face_detector_plugin.os create mode 100644 plugins/libzm_plugin_face_haar/src/face_detector_plugin.cpp create mode 100644 plugins/libzm_plugin_face_haar/src/face_detector_plugin.h create mode 100644 scripts/Makefile.am create mode 100644 scripts/Makefile.in create mode 100644 scripts/ZoneMinder/Changes create mode 100644 scripts/ZoneMinder/MANIFEST create mode 100644 scripts/ZoneMinder/META.yml create mode 100644 scripts/ZoneMinder/MYMETA.yml create mode 100644 scripts/ZoneMinder/Makefile.PL create mode 100644 scripts/ZoneMinder/Makefile.old create mode 100644 scripts/ZoneMinder/README create mode 100644 scripts/ZoneMinder/blib/arch/.exists create mode 100644 scripts/ZoneMinder/blib/arch/auto/ZoneMinder/.exists create mode 100644 scripts/ZoneMinder/blib/bin/.exists create mode 100644 scripts/ZoneMinder/blib/lib/.exists create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Base.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Config.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigAdmin.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigData.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/AxisV2.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Ncs370.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PanasonicIP.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PelcoD.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Visca.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Control/mjpgStreamer.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Database.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/General.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Logger.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Memory.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Mapped.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Shared.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/File.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Handle.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Inet.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Serial.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Spawning.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Unix.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection.pm create mode 100644 scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection/Example.pm create mode 100644 scripts/ZoneMinder/blib/lib/auto/ZoneMinder/.exists create mode 100644 scripts/ZoneMinder/blib/man1/.exists create mode 100644 scripts/ZoneMinder/blib/man3/.exists create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Base.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Config.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigAdmin.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigData.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::AxisV2.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Ncs370.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PanasonicIP.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PelcoD.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Visca.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Control::mjpgStreamer.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Database.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::General.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Logger.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Memory.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::File.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Handle.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Inet.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Serial.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Spawning.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Unix.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection.3pm create mode 100644 scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection::Example.3pm create mode 100644 scripts/ZoneMinder/blib/script/.exists create mode 100644 scripts/ZoneMinder/lib/ZoneMinder.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Base.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Config.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in.orig create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/Visca.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Database.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/General.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Logger.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Memory.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Memory/Shared.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm create mode 100644 scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm create mode 100644 scripts/ZoneMinder/pm_to_blib create mode 100644 scripts/ZoneMinder/t/ZoneMinder.t create mode 100644 scripts/zm create mode 100755 scripts/zm.in create mode 100644 scripts/zmaudit.pl create mode 100644 scripts/zmaudit.pl.in create mode 100644 scripts/zmcontrol.pl create mode 100644 scripts/zmcontrol.pl.in create mode 100644 scripts/zmdbbackup create mode 100644 scripts/zmdbbackup.in create mode 100644 scripts/zmdbrestore create mode 100644 scripts/zmdbrestore.in create mode 100644 scripts/zmdc.pl create mode 100644 scripts/zmdc.pl.in create mode 100644 scripts/zmeventdump create mode 100644 scripts/zmeventdump.in create mode 100644 scripts/zmfilter.pl create mode 100644 scripts/zmfilter.pl.in create mode 100644 scripts/zmlogrotate.conf create mode 100644 scripts/zmlogrotate.conf.in create mode 100644 scripts/zmpkg.pl create mode 100644 scripts/zmpkg.pl.in create mode 100644 scripts/zmtrack.pl create mode 100644 scripts/zmtrack.pl.in create mode 100644 scripts/zmtrigger.pl create mode 100644 scripts/zmtrigger.pl.in create mode 100644 scripts/zmupdate.pl create mode 100644 scripts/zmupdate.pl.in create mode 100644 scripts/zmvideo.pl create mode 100644 scripts/zmvideo.pl.in create mode 100644 scripts/zmwatch.pl create mode 100644 scripts/zmwatch.pl.in create mode 100644 scripts/zmx10.pl create mode 100644 scripts/zmx10.pl.in create mode 100644 src/.deps/zm.Po create mode 100644 src/.deps/zm_box.Po create mode 100644 src/.deps/zm_buffer.Po create mode 100644 src/.deps/zm_camera.Po create mode 100644 src/.deps/zm_comms.Po create mode 100644 src/.deps/zm_config.Po create mode 100644 src/.deps/zm_coord.Po create mode 100644 src/.deps/zm_db.Po create mode 100644 src/.deps/zm_detector.Po create mode 100644 src/.deps/zm_event.Po create mode 100644 src/.deps/zm_exception.Po create mode 100644 src/.deps/zm_ffmpeg.Po create mode 100644 src/.deps/zm_ffmpeg_camera.Po create mode 100644 src/.deps/zm_file_camera.Po create mode 100644 src/.deps/zm_image.Po create mode 100644 src/.deps/zm_image_analyser.Po create mode 100644 src/.deps/zm_jpeg.Po create mode 100644 src/.deps/zm_local_camera.Po create mode 100644 src/.deps/zm_logger.Po create mode 100644 src/.deps/zm_monitor.Po create mode 100644 src/.deps/zm_mpeg.Po create mode 100644 src/.deps/zm_plugin.Po create mode 100644 src/.deps/zm_plugin_manager.Po create mode 100644 src/.deps/zm_poly.Po create mode 100644 src/.deps/zm_regexp.Po create mode 100644 src/.deps/zm_remote_camera.Po create mode 100644 src/.deps/zm_remote_camera_http.Po create mode 100644 src/.deps/zm_remote_camera_rtsp.Po create mode 100644 src/.deps/zm_rtp.Po create mode 100644 src/.deps/zm_rtp_ctrl.Po create mode 100644 src/.deps/zm_rtp_data.Po create mode 100644 src/.deps/zm_rtp_source.Po create mode 100644 src/.deps/zm_rtsp.Po create mode 100644 src/.deps/zm_sdp.Po create mode 100644 src/.deps/zm_signal.Po create mode 100644 src/.deps/zm_stream.Po create mode 100644 src/.deps/zm_thread.Po create mode 100644 src/.deps/zm_time.Po create mode 100644 src/.deps/zm_timer.Po create mode 100644 src/.deps/zm_user.Po create mode 100644 src/.deps/zm_utils.Po create mode 100644 src/.deps/zm_zone.Po create mode 100644 src/.deps/zma.Po create mode 100644 src/.deps/zmc.Po create mode 100644 src/.deps/zmf.Po create mode 100644 src/.deps/zmfix.Po create mode 100644 src/.deps/zms.Po create mode 100644 src/.deps/zmstreamer.Po create mode 100644 src/.deps/zmu.Po create mode 100644 src/Makefile.am create mode 100644 src/Makefile.in create mode 100644 src/jinclude.h create mode 100644 src/zm.cpp create mode 100644 src/zm.h create mode 100644 src/zm_box.cpp create mode 100644 src/zm_box.h create mode 100644 src/zm_buffer.cpp create mode 100644 src/zm_buffer.h create mode 100644 src/zm_camera.cpp create mode 100644 src/zm_camera.h create mode 100644 src/zm_comms.cpp create mode 100644 src/zm_comms.h create mode 100644 src/zm_config.cpp create mode 100644 src/zm_config.h create mode 100644 src/zm_config.h.in create mode 100644 src/zm_config_defines.h create mode 100644 src/zm_coord.cpp create mode 100644 src/zm_coord.h create mode 100644 src/zm_db.cpp create mode 100644 src/zm_db.h create mode 100644 src/zm_detector.cpp create mode 100644 src/zm_detector.h create mode 100644 src/zm_event.cpp create mode 100644 src/zm_event.h create mode 100644 src/zm_exception.cpp create mode 100644 src/zm_exception.h create mode 100644 src/zm_ffmpeg.cpp create mode 100644 src/zm_ffmpeg.h create mode 100644 src/zm_ffmpeg_camera.cpp create mode 100644 src/zm_ffmpeg_camera.h create mode 100644 src/zm_file_camera.cpp create mode 100644 src/zm_file_camera.h create mode 100644 src/zm_font.h create mode 100644 src/zm_image.cpp create mode 100644 src/zm_image.h create mode 100644 src/zm_image_analyser.cpp create mode 100644 src/zm_image_analyser.h create mode 100644 src/zm_jpeg.cpp create mode 100644 src/zm_jpeg.h create mode 100644 src/zm_local_camera.cpp create mode 100644 src/zm_local_camera.h create mode 100644 src/zm_logger.cpp create mode 100644 src/zm_logger.h create mode 100644 src/zm_mem_utils.h create mode 100644 src/zm_monitor.cpp create mode 100644 src/zm_monitor.cpp.orig create mode 100644 src/zm_monitor.h create mode 100644 src/zm_monitor.h.orig create mode 100644 src/zm_mpeg.cpp create mode 100644 src/zm_mpeg.h create mode 100644 src/zm_plugin.cpp create mode 100644 src/zm_plugin.h create mode 100644 src/zm_plugin_manager.cpp create mode 100644 src/zm_plugin_manager.h create mode 100644 src/zm_poly.cpp create mode 100644 src/zm_poly.h create mode 100644 src/zm_regexp.cpp create mode 100644 src/zm_regexp.h create mode 100644 src/zm_remote_camera.cpp create mode 100644 src/zm_remote_camera.h create mode 100644 src/zm_remote_camera_http.cpp create mode 100644 src/zm_remote_camera_http.h create mode 100644 src/zm_remote_camera_rtsp.cpp create mode 100644 src/zm_remote_camera_rtsp.h create mode 100644 src/zm_rgb.h create mode 100644 src/zm_rtp.cpp create mode 100644 src/zm_rtp.h create mode 100644 src/zm_rtp_ctrl.cpp create mode 100644 src/zm_rtp_ctrl.h create mode 100644 src/zm_rtp_data.cpp create mode 100644 src/zm_rtp_data.h create mode 100644 src/zm_rtp_source.cpp create mode 100644 src/zm_rtp_source.h create mode 100644 src/zm_rtsp.cpp create mode 100644 src/zm_rtsp.h create mode 100644 src/zm_sdp.cpp create mode 100644 src/zm_sdp.h create mode 100644 src/zm_signal.cpp create mode 100644 src/zm_signal.h create mode 100644 src/zm_stream.cpp create mode 100644 src/zm_stream.h create mode 100644 src/zm_thread.cpp create mode 100644 src/zm_thread.h create mode 100644 src/zm_threaddata.cpp create mode 100644 src/zm_time.cpp create mode 100644 src/zm_time.h create mode 100644 src/zm_timer.cpp create mode 100644 src/zm_timer.h create mode 100644 src/zm_user.cpp create mode 100644 src/zm_user.h create mode 100644 src/zm_utils.cpp create mode 100644 src/zm_utils.h create mode 100644 src/zm_zone.cpp create mode 100644 src/zm_zone.cpp.orig create mode 100644 src/zm_zone.h create mode 100644 src/zm_zone.h.orig create mode 100644 src/zma.cpp create mode 100644 src/zmc.cpp create mode 100644 src/zmf.cpp create mode 100644 src/zmf.h create mode 100644 src/zmfix.cpp create mode 100644 src/zms.cpp create mode 100644 src/zmstreamer.cpp create mode 100644 src/zmu.cpp create mode 100644 stamp-h.in create mode 100644 stamp-h1 create mode 100755 umutils/nextimeconfigure.zm create mode 100644 web/Makefile.am create mode 100644 web/Makefile.in create mode 100644 web/ajax/Makefile.am create mode 100644 web/ajax/Makefile.in create mode 100644 web/ajax/alarm.php create mode 100644 web/ajax/control.php create mode 100644 web/ajax/event.php create mode 100644 web/ajax/log.php create mode 100644 web/ajax/status.php create mode 100644 web/ajax/stream.php create mode 100644 web/ajax/zone.php create mode 100644 web/css/Makefile.am create mode 100644 web/css/Makefile.in create mode 100644 web/css/overlay.css create mode 100644 web/css/reset.css create mode 100644 web/css/spinner.css create mode 100644 web/graphics/Makefile.am create mode 100644 web/graphics/Makefile.in create mode 100644 web/graphics/favicon.ico create mode 100644 web/graphics/spinner.gif create mode 100644 web/graphics/transparent.gif create mode 100644 web/includes/Makefile.am create mode 100644 web/includes/Makefile.in create mode 100644 web/includes/actions.php create mode 100644 web/includes/config.php create mode 100644 web/includes/config.php.in create mode 100644 web/includes/control_functions.php create mode 100644 web/includes/database.php create mode 100644 web/includes/functions.php create mode 100644 web/includes/lang.php create mode 100644 web/includes/logger.php create mode 100644 web/index.php create mode 100644 web/js/Makefile.am create mode 100644 web/js/Makefile.in create mode 100644 web/js/logger.js create mode 100644 web/js/mootools.ext.js create mode 100644 web/js/overlay.js create mode 100644 web/lang/Makefile.am create mode 100644 web/lang/Makefile.in create mode 100644 web/lang/big5_big5.php create mode 100644 web/lang/big5_big5.php.orig create mode 100644 web/lang/cn_zh.php create mode 100644 web/lang/cn_zh.php.orig create mode 100644 web/lang/cs_cz.php create mode 100644 web/lang/cs_cz.php.orig create mode 100644 web/lang/de_de.php create mode 100644 web/lang/de_de.php.orig create mode 100644 web/lang/dk_dk.php create mode 100644 web/lang/dk_dk.php.orig create mode 100644 web/lang/en_gb.php create mode 100644 web/lang/en_gb.php.orig create mode 100644 web/lang/en_us.php create mode 100644 web/lang/es_ar.php create mode 100644 web/lang/es_ar.php.orig create mode 100644 web/lang/es_es.php create mode 100644 web/lang/et_ee.php create mode 100644 web/lang/fr_fr.php create mode 100644 web/lang/fr_fr.php.orig create mode 100755 web/lang/he_il.php create mode 100755 web/lang/he_il.php.orig create mode 100644 web/lang/hu_hu.php create mode 100644 web/lang/hu_hu.php.orig create mode 100644 web/lang/it_it.php create mode 100644 web/lang/it_it.php.orig create mode 100644 web/lang/ja_jp.php create mode 100644 web/lang/ja_jp.php.orig create mode 100644 web/lang/nl_nl.php create mode 100644 web/lang/nl_nl.php.orig create mode 100644 web/lang/pl_pl.php create mode 100644 web/lang/pl_pl.php.orig create mode 100644 web/lang/pt_br.php create mode 100644 web/lang/pt_br.php.orig create mode 100755 web/lang/ro_ro.php create mode 100755 web/lang/ro_ro.php.orig create mode 100644 web/lang/ru_ru.php create mode 100644 web/lang/ru_ru.php.orig create mode 100644 web/lang/se_se.php create mode 100644 web/lang/se_se.php.orig create mode 100644 web/lang/updateLangs.php create mode 100644 web/scripts/retag.sh create mode 100644 web/scripts/swap.pl create mode 100644 web/skins/Makefile.am create mode 100644 web/skins/Makefile.in create mode 100644 web/skins/classic/Makefile.am create mode 100644 web/skins/classic/Makefile.in create mode 100644 web/skins/classic/ajax/Makefile.am create mode 100644 web/skins/classic/ajax/Makefile.in create mode 100644 web/skins/classic/css/Makefile.am create mode 100644 web/skins/classic/css/Makefile.in create mode 100644 web/skins/classic/css/control.css create mode 100644 web/skins/classic/css/export.css create mode 100644 web/skins/classic/css/skin.css create mode 100644 web/skins/classic/graphics/Makefile.am create mode 100644 web/skins/classic/graphics/Makefile.in create mode 100644 web/skins/classic/graphics/arrow-d.gif create mode 100644 web/skins/classic/graphics/arrow-dl.gif create mode 100644 web/skins/classic/graphics/arrow-dr.gif create mode 100644 web/skins/classic/graphics/arrow-l-d.gif create mode 100644 web/skins/classic/graphics/arrow-l-u.gif create mode 100644 web/skins/classic/graphics/arrow-l.gif create mode 100644 web/skins/classic/graphics/arrow-r.gif create mode 100644 web/skins/classic/graphics/arrow-s-d.gif create mode 100644 web/skins/classic/graphics/arrow-s-u.gif create mode 100644 web/skins/classic/graphics/arrow-u.gif create mode 100644 web/skins/classic/graphics/arrow-ul.gif create mode 100644 web/skins/classic/graphics/arrow-ur.gif create mode 100644 web/skins/classic/graphics/center.gif create mode 100644 web/skins/classic/graphics/point-g.gif create mode 100644 web/skins/classic/graphics/point-o.gif create mode 100644 web/skins/classic/graphics/point-r.gif create mode 100644 web/skins/classic/graphics/seq-d.gif create mode 100644 web/skins/classic/graphics/seq-u.gif create mode 100644 web/skins/classic/includes/Makefile.am create mode 100644 web/skins/classic/includes/Makefile.in create mode 100644 web/skins/classic/includes/config.php create mode 100644 web/skins/classic/includes/control_functions.php create mode 100644 web/skins/classic/includes/export_functions.php create mode 100644 web/skins/classic/includes/functions.php create mode 100644 web/skins/classic/includes/init.php create mode 100644 web/skins/classic/includes/timeline_functions.php create mode 100644 web/skins/classic/js/Makefile.am create mode 100644 web/skins/classic/js/Makefile.in create mode 100644 web/skins/classic/js/skin.js create mode 100644 web/skins/classic/js/skin.js.php create mode 100644 web/skins/classic/lang/Makefile.am create mode 100644 web/skins/classic/lang/Makefile.in create mode 100644 web/skins/classic/skin.php create mode 100644 web/skins/classic/svn-commit.tmp create mode 100644 web/skins/classic/views/Makefile.am create mode 100644 web/skins/classic/views/Makefile.in create mode 100644 web/skins/classic/views/bandwidth.php create mode 100644 web/skins/classic/views/blank.php create mode 100644 web/skins/classic/views/console.php create mode 100644 web/skins/classic/views/control.php create mode 100644 web/skins/classic/views/controlcap.php create mode 100644 web/skins/classic/views/controlcaps.php create mode 100644 web/skins/classic/views/controlpreset.php create mode 100644 web/skins/classic/views/css/Makefile.am create mode 100644 web/skins/classic/views/css/Makefile.in create mode 100644 web/skins/classic/views/css/console.css create mode 100644 web/skins/classic/views/css/control.css create mode 100644 web/skins/classic/views/css/controlcaps.css create mode 100644 web/skins/classic/views/css/devices.css create mode 100644 web/skins/classic/views/css/event.css create mode 100644 web/skins/classic/views/css/events.css create mode 100644 web/skins/classic/views/css/export.css create mode 100644 web/skins/classic/views/css/filter.css create mode 100644 web/skins/classic/views/css/frame.css create mode 100644 web/skins/classic/views/css/frames.css create mode 100644 web/skins/classic/views/css/groups.css create mode 100644 web/skins/classic/views/css/log.css create mode 100644 web/skins/classic/views/css/monitor.css create mode 100644 web/skins/classic/views/css/montage.css create mode 100644 web/skins/classic/views/css/montage_2wide.css create mode 100644 web/skins/classic/views/css/montage_3wide.css create mode 100644 web/skins/classic/views/css/montage_3wide50enlarge.css create mode 100644 web/skins/classic/views/css/montage_4wide.css create mode 100644 web/skins/classic/views/css/montage_freeform.css create mode 100644 web/skins/classic/views/css/options.css create mode 100644 web/skins/classic/views/css/plugin.css create mode 100644 web/skins/classic/views/css/stats.css create mode 100644 web/skins/classic/views/css/timeline.css create mode 100644 web/skins/classic/views/css/timeline.css.php create mode 100644 web/skins/classic/views/css/video.css create mode 100644 web/skins/classic/views/css/watch.css create mode 100644 web/skins/classic/views/css/zone.css create mode 100644 web/skins/classic/views/cycle.php create mode 100644 web/skins/classic/views/device.php create mode 100644 web/skins/classic/views/devices.php create mode 100644 web/skins/classic/views/donate.php create mode 100644 web/skins/classic/views/error.php create mode 100644 web/skins/classic/views/event.php create mode 100644 web/skins/classic/views/eventdetail.php create mode 100644 web/skins/classic/views/events.php create mode 100644 web/skins/classic/views/export.php create mode 100644 web/skins/classic/views/filter.php create mode 100644 web/skins/classic/views/filtersave.php create mode 100644 web/skins/classic/views/frame.php create mode 100644 web/skins/classic/views/frames.php create mode 100644 web/skins/classic/views/function.php create mode 100644 web/skins/classic/views/group.php create mode 100644 web/skins/classic/views/groups.php create mode 100644 web/skins/classic/views/js/Makefile.am create mode 100644 web/skins/classic/views/js/Makefile.in create mode 100644 web/skins/classic/views/js/console.js create mode 100644 web/skins/classic/views/js/console.js.php create mode 100644 web/skins/classic/views/js/control.js create mode 100644 web/skins/classic/views/js/controlpreset.js create mode 100644 web/skins/classic/views/js/controlpreset.js.php create mode 100644 web/skins/classic/views/js/cycle.js create mode 100644 web/skins/classic/views/js/cycle.js.php create mode 100644 web/skins/classic/views/js/devices.js create mode 100644 web/skins/classic/views/js/donate.js create mode 100644 web/skins/classic/views/js/donate.js.php create mode 100644 web/skins/classic/views/js/event.js create mode 100644 web/skins/classic/views/js/event.js.php create mode 100644 web/skins/classic/views/js/events.js create mode 100644 web/skins/classic/views/js/events.js.php create mode 100644 web/skins/classic/views/js/export.js create mode 100644 web/skins/classic/views/js/export.js.php create mode 100644 web/skins/classic/views/js/filter.js create mode 100644 web/skins/classic/views/js/filter.js.php create mode 100644 web/skins/classic/views/js/group.js create mode 100644 web/skins/classic/views/js/groups.js create mode 100644 web/skins/classic/views/js/log.js create mode 100644 web/skins/classic/views/js/login.js create mode 100644 web/skins/classic/views/js/monitor.js create mode 100644 web/skins/classic/views/js/monitor.js.php create mode 100644 web/skins/classic/views/js/monitorpreset.js create mode 100644 web/skins/classic/views/js/monitorprobe.js create mode 100644 web/skins/classic/views/js/montage.js create mode 100644 web/skins/classic/views/js/montage.js.php create mode 100644 web/skins/classic/views/js/options.js.php create mode 100644 web/skins/classic/views/js/plugin.js create mode 100644 web/skins/classic/views/js/plugin.js.php create mode 100644 web/skins/classic/views/js/postlogin.js create mode 100644 web/skins/classic/views/js/state.js create mode 100644 web/skins/classic/views/js/state.js.php create mode 100644 web/skins/classic/views/js/timeline.js create mode 100644 web/skins/classic/views/js/timeline.js.php create mode 100644 web/skins/classic/views/js/user.js create mode 100644 web/skins/classic/views/js/version.js create mode 100644 web/skins/classic/views/js/version.js.php create mode 100644 web/skins/classic/views/js/video.js create mode 100644 web/skins/classic/views/js/video.js.php create mode 100644 web/skins/classic/views/js/watch.js create mode 100644 web/skins/classic/views/js/watch.js.php create mode 100644 web/skins/classic/views/js/zone.js create mode 100644 web/skins/classic/views/js/zone.js.php create mode 100644 web/skins/classic/views/log.php create mode 100644 web/skins/classic/views/login.php create mode 100644 web/skins/classic/views/logout.php create mode 100644 web/skins/classic/views/monitor.php create mode 100644 web/skins/classic/views/monitor.php.orig create mode 100644 web/skins/classic/views/monitorpreset.php create mode 100644 web/skins/classic/views/monitorprobe.php create mode 100644 web/skins/classic/views/montage.php create mode 100644 web/skins/classic/views/none.php create mode 100644 web/skins/classic/views/optionhelp.php create mode 100644 web/skins/classic/views/options.php create mode 100644 web/skins/classic/views/plugin.php create mode 100644 web/skins/classic/views/postlogin.php create mode 100644 web/skins/classic/views/settings.php create mode 100644 web/skins/classic/views/state.php create mode 100644 web/skins/classic/views/stats.php create mode 100644 web/skins/classic/views/status.php create mode 100644 web/skins/classic/views/timeline.php create mode 100644 web/skins/classic/views/user.php create mode 100644 web/skins/classic/views/version.php create mode 100644 web/skins/classic/views/video.php create mode 100644 web/skins/classic/views/watch.php create mode 100644 web/skins/classic/views/zone.php create mode 100644 web/skins/classic/views/zones.php create mode 100644 web/skins/mobile/Makefile.am create mode 100644 web/skins/mobile/Makefile.in create mode 100644 web/skins/mobile/ajax/Makefile.am create mode 100644 web/skins/mobile/ajax/Makefile.in create mode 100644 web/skins/mobile/css/Makefile.am create mode 100644 web/skins/mobile/css/Makefile.in create mode 100644 web/skins/mobile/css/skin.css create mode 100644 web/skins/mobile/graphics/Makefile.am create mode 100644 web/skins/mobile/graphics/Makefile.in create mode 100644 web/skins/mobile/includes/Makefile.am create mode 100644 web/skins/mobile/includes/Makefile.in create mode 100644 web/skins/mobile/includes/config.php create mode 100644 web/skins/mobile/includes/control_functions.php create mode 100644 web/skins/mobile/includes/functions.php create mode 100644 web/skins/mobile/includes/init.php create mode 100644 web/skins/mobile/lang/Makefile.am create mode 100644 web/skins/mobile/lang/Makefile.in create mode 100644 web/skins/mobile/skin.php create mode 100644 web/skins/mobile/views/Makefile.am create mode 100644 web/skins/mobile/views/Makefile.in create mode 100644 web/skins/mobile/views/console.php create mode 100644 web/skins/mobile/views/css/Makefile.am create mode 100644 web/skins/mobile/views/css/Makefile.in create mode 100644 web/skins/mobile/views/css/console.css create mode 100644 web/skins/mobile/views/devices.php create mode 100644 web/skins/mobile/views/error.php create mode 100644 web/skins/mobile/views/event.php create mode 100644 web/skins/mobile/views/eventdetails.php create mode 100644 web/skins/mobile/views/events.php create mode 100644 web/skins/mobile/views/filter.php create mode 100644 web/skins/mobile/views/frame.php create mode 100644 web/skins/mobile/views/function.php create mode 100644 web/skins/mobile/views/login.php create mode 100644 web/skins/mobile/views/montage.php create mode 100644 web/skins/mobile/views/state.php create mode 100644 web/skins/mobile/views/video.php create mode 100644 web/skins/mobile/views/watch.php create mode 100644 web/skins/xml/Makefile.am create mode 100644 web/skins/xml/Makefile.in create mode 100644 web/skins/xml/includes/Makefile.am create mode 100644 web/skins/xml/includes/Makefile.in create mode 100644 web/skins/xml/includes/config.php create mode 100644 web/skins/xml/includes/functions.php create mode 100644 web/skins/xml/includes/init.php create mode 100644 web/skins/xml/skin.php create mode 100644 web/skins/xml/views/Makefile.am create mode 100644 web/skins/xml/views/Makefile.in create mode 100644 web/skins/xml/views/actions.php create mode 100644 web/skins/xml/views/console.php create mode 100644 web/skins/xml/views/none.php create mode 100644 web/skins/xml/views/notfound.png create mode 100644 web/tools/Makefile.am create mode 100644 web/tools/Makefile.in create mode 100644 web/tools/mootools/Makefile.am create mode 100644 web/tools/mootools/Makefile.in create mode 100644 web/tools/mootools/mootools-core-1.3.2-nc.js create mode 100644 web/tools/mootools/mootools-core-1.3.2-yc.js create mode 100644 web/tools/mootools/mootools-more-1.3.2.1-nc.js create mode 100644 web/tools/mootools/mootools-more-1.3.2.1-yc.js create mode 100644 web/views/Makefile.am create mode 100644 web/views/Makefile.in create mode 100644 web/views/file.php create mode 100644 web/views/image.php create mode 100644 zm.conf.in create mode 100644 zmconfgen.pl.in diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 000000000..a93b5355b --- /dev/null +++ b/AUTHORS @@ -0,0 +1,10 @@ +ZoneMinder - A Linux based camera monitoring and analysis tool. + +This project was imagined and created by Philip Coombes in +September 2002, shortly after being burglarised of his power tools. + +mailto:philip.coombes@zoneminder.com + +Plugin architecture and sample plugin modified for this version of ZoneMinder +with support of Stagecoach Wireless (mailto:beat.naef@stagecoach-wireless.com) +and the contributions of the CVisionLab team diff --git a/BUGS b/BUGS new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/BUGS @@ -0,0 +1 @@ +Please see README file. diff --git a/COPYING b/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/ChangeLog @@ -0,0 +1 @@ +Please see README file. diff --git a/INSTALL b/INSTALL new file mode 100644 index 000000000..1de0ac2ad --- /dev/null +++ b/INSTALL @@ -0,0 +1,185 @@ +Basic Installation +================== + + These are generic installation instructions. + + Please see http://www.zoneminder.com/wiki/index.php/Documentation + for full details. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 000000000..4f29b67ea --- /dev/null +++ b/Makefile.am @@ -0,0 +1,32 @@ +AUTOMAKE_OPTIONS = gnu + +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ + +sysconf_DATA = \ + zm.conf + +SUBDIRS = \ + src \ + web \ + scripts \ + db \ + misc + +EXTRA_DIST = \ + zm.conf.in \ + zmconfgen.pl.in + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(sysconfdir); chown $(webuser):$(webgroup) $(sysconf_DATA); chmod 600 $(sysconf_DATA) ) + ( if ! test -e $(ZM_RUNDIR); then mkdir -p $(ZM_RUNDIR); fi; if test "$(ZM_RUNDIR)" != "/var/run"; then chown $(webuser):$(webgroup) $(ZM_RUNDIR); chmod u+w $(ZM_RUNDIR); fi ) + ( if ! test -e $(ZM_TMPDIR); then mkdir -m 700 -p $(ZM_TMPDIR); fi; if test "$(ZM_TMPDIR)" != "/tmp"; then chown $(webuser):$(webgroup) $(ZM_TMPDIR); chmod u+w $(ZM_TMPDIR); fi ) + ( if ! test -e $(ZM_LOGDIR); then mkdir -p $(ZM_LOGDIR); fi; if test "$(ZM_LOGDIR)" != "/var/log"; then chown $(webuser):$(webgroup) $(ZM_LOGDIR); chmod u+w $(ZM_LOGDIR); fi ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -rf events graphics images sounds temp ) + @-( if test "$(ZM_RUNDIR)" != "/var/run"; then rm -rf $(ZM_RUNDIR); fi ) + @-( if test "$(ZM_TMPDIR)" != "/tmp"; then rm -rf $(ZM_TMPDIR); fi ) + @-( if test "$(ZM_LOGDIR)" != "/var/log"; then rm -rf $(ZM_LOGDIR); fi ) diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 000000000..91a2c41d3 --- /dev/null +++ b/Makefile.in @@ -0,0 +1,880 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = . +DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.h.in \ + $(srcdir)/zm.conf.in $(srcdir)/zmconfgen.pl.in \ + $(top_srcdir)/configure \ + $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in \ + $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in \ + $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in \ + $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in \ + AUTHORS COPYING ChangeLog INSTALL NEWS TODO depcomp install-sh \ + missing mkinstalldirs +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno config.status.lineno +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = zm.conf zmconfgen.pl \ + scripts/ZoneMinder/lib/ZoneMinder/Base.pm \ + scripts/ZoneMinder/lib/ZoneMinder/Config.pm \ + scripts/ZoneMinder/lib/ZoneMinder/Memory.pm \ + scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(sysconfdir)" +DATA = $(sysconf_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir dist dist-all distcheck +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +distdir = $(PACKAGE)-$(VERSION) +top_distdir = $(distdir) +am__remove_distdir = \ + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +DIST_ARCHIVES = $(distdir).tar.gz +GZIP_ENV = --best +distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' +distcleancheck_listfiles = find . -type f -print +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu + +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ +sysconf_DATA = \ + zm.conf + +SUBDIRS = \ + src \ + web \ + scripts \ + db \ + misc + +EXTRA_DIST = \ + zm.conf.in \ + zmconfgen.pl.in + +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: +am--refresh: Makefile + @: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \ + $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + echo ' $(SHELL) ./config.status'; \ + $(SHELL) ./config.status;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck + +$(top_srcdir)/configure: $(am__configure_deps) + $(am__cd) $(srcdir) && $(AUTOCONF) +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) +$(am__aclocal_m4_deps): + +config.h: stamp-h1 + @if test ! -f $@; then rm -f stamp-h1; else :; fi + @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h +$(srcdir)/config.h.in: $(am__configure_deps) + ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) + rm -f stamp-h1 + touch $@ + +distclean-hdr: + -rm -f config.h stamp-h1 +zm.conf: $(top_builddir)/config.status $(srcdir)/zm.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +zmconfgen.pl: $(top_builddir)/config.status $(srcdir)/zmconfgen.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +scripts/ZoneMinder/lib/ZoneMinder/Base.pm: $(top_builddir)/config.status $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +scripts/ZoneMinder/lib/ZoneMinder/Config.pm: $(top_builddir)/config.status $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +scripts/ZoneMinder/lib/ZoneMinder/Memory.pm: $(top_builddir)/config.status $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm: $(top_builddir)/config.status $(top_srcdir)/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in + cd $(top_builddir) && $(SHELL) ./config.status $@ +install-sysconfDATA: $(sysconf_DATA) + @$(NORMAL_INSTALL) + @list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sysconfdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sysconfdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(sysconfdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(sysconfdir)" || exit $$?; \ + done + +uninstall-sysconfDATA: + @$(NORMAL_UNINSTALL) + @list='$(sysconf_DATA)'; test -n "$(sysconfdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(sysconfdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + $(am__remove_distdir) + test -d "$(distdir)" || mkdir "$(distdir)" + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done + -test -n "$(am__skip_mode_fix)" \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r "$(distdir)" +dist-gzip: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist-bzip2: distdir + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__remove_distdir) + +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__remove_distdir) + +dist-lzma: distdir + tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma + $(am__remove_distdir) + +dist-xz: distdir + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__remove_distdir) + +dist-tarZ: distdir + tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z + $(am__remove_distdir) + +dist-shar: distdir + shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz + $(am__remove_distdir) + +dist-zip: distdir + -rm -f $(distdir).zip + zip -rq $(distdir).zip $(distdir) + $(am__remove_distdir) + +dist dist-all: distdir + tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + case '$(DIST_ARCHIVES)' in \ + *.tar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ + *.tar.bz2*) \ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lzma*) \ + lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ + *.tar.xz*) \ + xz -dc $(distdir).tar.xz | $(am__untar) ;;\ + *.tar.Z*) \ + uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ + *.shar.gz*) \ + GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ + *.zip*) \ + unzip $(distdir).zip ;;\ + esac + chmod -R a-w $(distdir); chmod u+w $(distdir) + mkdir $(distdir)/_build + mkdir $(distdir)/_inst + chmod a-w $(distdir) + test -d $(distdir)/_build || exit 0; \ + dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ + && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ + && am__cwd=`pwd` \ + && $(am__cd) $(distdir)/_build \ + && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ + distuninstallcheck \ + && chmod -R a-w "$$dc_install_base" \ + && ({ \ + (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ + && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ + distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ + } || { rm -rf "$$dc_destdir"; exit 1; }) \ + && rm -rf "$$dc_destdir" \ + && $(MAKE) $(AM_MAKEFLAGS) dist \ + && rm -rf $(DIST_ARCHIVES) \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ + && cd "$$am__cwd" \ + || exit 1 + $(am__remove_distdir) + @(echo "$(distdir) archives ready for distribution: "; \ + list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ + sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' +distuninstallcheck: + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after uninstall:" ; \ + if test -n "$(DESTDIR)"; then \ + echo " (check DESTDIR support)"; \ + fi ; \ + $(distuninstallcheck_listfiles) ; \ + exit 1; } >&2 +distcleancheck: distclean + @if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left in build directory after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) config.h +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(sysconfdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-hdr distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-sysconfDATA + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf $(top_srcdir)/autom4te.cache + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-sysconfDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \ + ctags-recursive install-am install-data-am install-strip \ + tags-recursive uninstall-am + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am am--refresh check check-am clean clean-generic \ + ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \ + dist-lzip dist-lzma dist-shar dist-tarZ dist-xz dist-zip \ + distcheck distclean distclean-generic distclean-hdr \ + distclean-tags distcleancheck distdir distuninstallcheck dvi \ + dvi-am html html-am info info-am install install-am \ + install-data install-data-am install-data-hook install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip install-sysconfDATA installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-hook uninstall-sysconfDATA + + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(sysconfdir); chown $(webuser):$(webgroup) $(sysconf_DATA); chmod 600 $(sysconf_DATA) ) + ( if ! test -e $(ZM_RUNDIR); then mkdir -p $(ZM_RUNDIR); fi; if test "$(ZM_RUNDIR)" != "/var/run"; then chown $(webuser):$(webgroup) $(ZM_RUNDIR); chmod u+w $(ZM_RUNDIR); fi ) + ( if ! test -e $(ZM_TMPDIR); then mkdir -m 700 -p $(ZM_TMPDIR); fi; if test "$(ZM_TMPDIR)" != "/tmp"; then chown $(webuser):$(webgroup) $(ZM_TMPDIR); chmod u+w $(ZM_TMPDIR); fi ) + ( if ! test -e $(ZM_LOGDIR); then mkdir -p $(ZM_LOGDIR); fi; if test "$(ZM_LOGDIR)" != "/var/log"; then chown $(webuser):$(webgroup) $(ZM_LOGDIR); chmod u+w $(ZM_LOGDIR); fi ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -rf events graphics images sounds temp ) + @-( if test "$(ZM_RUNDIR)" != "/var/run"; then rm -rf $(ZM_RUNDIR); fi ) + @-( if test "$(ZM_TMPDIR)" != "/tmp"; then rm -rf $(ZM_TMPDIR); fi ) + @-( if test "$(ZM_LOGDIR)" != "/var/log"; then rm -rf $(ZM_LOGDIR); fi ) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/NEWS b/NEWS new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/NEWS @@ -0,0 +1 @@ +Please see README file. diff --git a/README b/README new file mode 100644 index 000000000..e3dfa62e1 --- /dev/null +++ b/README @@ -0,0 +1,5 @@ + +All documentation for ZoneMinder is now online at + +http://www.zoneminder.com/wiki/index.php/Documentation + diff --git a/TODO b/TODO new file mode 100644 index 000000000..69af9c87e --- /dev/null +++ b/TODO @@ -0,0 +1,2 @@ +Please see README file. + diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 000000000..605842149 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,74 @@ +AC_DEFUN([AC_DEFINE_DIR], [ + prefix_NONE= + exec_prefix_NONE= + test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix +dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn +dnl refers to ${prefix}. Thus we have to use `eval' twice. + eval ac_define_dir="\"[$]$2\"" + eval ac_define_dir="\"$ac_define_dir\"" + AC_SUBST($1, "$ac_define_dir") + AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3]) + test "$prefix_NONE" && prefix=NONE + test "$exec_prefix_NONE" && exec_prefix=NONE +]) + +AC_DEFUN([AC_PROG_PERL_VERSION],[dnl +# Make sure we have perl +if test -z "$PERL"; then +AC_CHECK_PROG(PERL,perl,perl) +fi + +# Check if version of Perl is sufficient +ac_perl_version="$1" + +if test "x$PERL" != "x"; then + AC_MSG_CHECKING(for perl version greater than or equal to $ac_perl_version) + # NB: It would be nice to log the error if there is one, but we cannot rely + # on autoconf internals + $PERL -e "use $ac_perl_version;" > /dev/null 2>&1 + if test $? -ne 0; then + AC_MSG_RESULT(no); + $3 + else + AC_MSG_RESULT(ok); + $2 + fi +else + AC_MSG_WARN(could not find perl) +fi +])dnl + +AC_DEFUN([AC_PROG_PERL_MODULES],[dnl +ac_perl_modules="$1" +# Make sure we have perl +if test -z "$PERL"; then +AC_CHECK_PROG(PERL,perl,perl) +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + AC_MSG_CHECKING(for perl module $ac_perl_module) + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + AC_MSG_RESULT(no); + ac_perl_modules_failed=1 + else + AC_MSG_RESULT(ok); + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + $2 + else + : + $3 + fi +else + AC_MSG_WARN(could not find perl) +fi])dnl diff --git a/aclocal.m4 b/aclocal.m4 new file mode 100644 index 000000000..8ba41b05f --- /dev/null +++ b/aclocal.m4 @@ -0,0 +1,984 @@ +# generated automatically by aclocal 1.11.6 -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. +You have another version of autoconf. It may work, but is not guaranteed to. +If you have problems, you may need to regenerate the build system entirely. +To do so, use the procedure documented by the package, typically `autoreconf'.])]) + +# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008, 2011 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +# (This private macro should not be called outside this file.) +AC_DEFUN([AM_AUTOMAKE_VERSION], +[am__api_version='1.11' +dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to +dnl require some minimum version. Point them to the right macro. +m4_if([$1], [1.11.6], [], + [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl +]) + +# _AM_AUTOCONF_VERSION(VERSION) +# ----------------------------- +# aclocal traces this macro to find the Autoconf version. +# This is a private macro too. Using m4_define simplifies +# the logic in aclocal, which can simply ignore this definition. +m4_define([_AM_AUTOCONF_VERSION], []) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. +# This function is AC_REQUIREd by AM_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], +[AM_AUTOMAKE_VERSION([1.11.6])dnl +m4_ifndef([AC_AUTOCONF_VERSION], + [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl +_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) + +# AM_AUX_DIR_EXPAND -*- Autoconf -*- + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +AC_DEFUN([AM_AUX_DIR_EXPAND], +[dnl Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50])dnl +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 9 + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[AC_PREREQ(2.52)dnl + ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE])dnl +AC_SUBST([$1_FALSE])dnl +_AM_SUBST_NOTMAKE([$1_TRUE])dnl +_AM_SUBST_NOTMAKE([$1_FALSE])dnl +m4_define([_AM_COND_VALUE_$1], [$2])dnl +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([[conditional "$1" was never defined. +Usually this means the macro was only invoked conditionally.]]) +fi])]) + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, +# 2010, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 12 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], UPC, [depcc="$UPC" am_compiler_list=], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + am__universal=false + m4_case([$1], [CC], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac], + [CXX], + [case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac]) + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +AM_CONDITIONAL([am__fastdep$1], [ + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[AC_REQUIRE([AM_SET_LEADING_DOT])dnl +AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH])dnl +_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +#serial 5 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[{ + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 8 + +# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. +AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + +# Do all the work for Automake. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, +# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 16 + +# This macro actually does too much. Some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_PREREQ([2.62])dnl +dnl Autoconf wants to disallow AM_ names. We explicitly allow +dnl the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl +AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl +AC_REQUIRE([AC_PROG_INSTALL])dnl +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi +AC_SUBST([CYGPATH_W]) + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl +dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. +m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, + [m4_fatal([AC_INIT should be called with package and version arguments])])dnl + AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl + AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl +AC_REQUIRE([AM_PROG_MKDIR_P])dnl +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl +AC_REQUIRE([AM_SET_LEADING_DOT])dnl +_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], + [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], + [_AM_PROG_TAR([v7])])]) +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_CC], + defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_CXX], + defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJC], + [_AM_DEPENDENCIES(OBJC)], + [define([AC_PROG_OBJC], + defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl +]) +_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl +dnl The `parallel-tests' driver may need to know about EXEEXT, so add the +dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro +dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_CONFIG_COMMANDS_PRE(dnl +[m4_provide_if([_AM_COMPILER_EXEEXT], + [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl +]) + +dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further +dnl mangled by Autoconf and run in a shell conditional statement. +m4_define([_AC_COMPILER_EXEEXT], +m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) + + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. The stamp files are numbered to have different names. + +# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the +# loop where config.status creates the headers, so we can generate +# our stamp files there. +AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], +[# Compute $1's index in $config_headers. +_am_arg=$1 +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) + +# Copyright (C) 2001, 2003, 2005, 2008, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi +AC_SUBST(install_sh)]) + +# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# Check whether the underlying file-system supports filenames +# with a leading dot. For instance MS-DOS doesn't. +AC_DEFUN([AM_SET_LEADING_DOT], +[rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null +AC_SUBST([am__leading_dot])]) + +# Check to see how 'make' treats includes. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 4 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi +AC_SUBST([am__include]) +AC_SUBST([am__quote]) +AC_MSG_RESULT([$_am_result]) +rm -f confinc confmf +]) + +# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- + +# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 6 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([missing])dnl +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# Copyright (C) 2003, 2004, 2005, 2006, 2011 Free Software Foundation, +# Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_MKDIR_P +# --------------- +# Check for `mkdir -p'. +AC_DEFUN([AM_PROG_MKDIR_P], +[AC_PREREQ([2.60])dnl +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, +dnl while keeping a definition of mkdir_p for backward compatibility. +dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. +dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of +dnl Makefile.ins that do not define MKDIR_P, so we do our own +dnl adjustment using top_builddir (which is defined more often than +dnl MKDIR_P). +AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl +case $mkdir_p in + [[\\/$]]* | ?:[[\\/]]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac +]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright (C) 2001, 2002, 2003, 2005, 2008, 2010 Free Software +# Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# -------------------- +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ------------------------ +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 +# Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 5 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[[\\\"\#\$\&\'\`$am_lf]]*) + AC_MSG_ERROR([unsafe absolute working directory name]);; +esac +case $srcdir in + *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) + AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# Copyright (C) 2001, 2003, 2005, 2011 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 1 + +# AM_PROG_INSTALL_STRIP +# --------------------- +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# Copyright (C) 2006, 2008, 2010 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 3 + +# _AM_SUBST_NOTMAKE(VARIABLE) +# --------------------------- +# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. +# This macro is traced by Automake. +AC_DEFUN([_AM_SUBST_NOTMAKE]) + +# AM_SUBST_NOTMAKE(VARIABLE) +# -------------------------- +# Public sister of _AM_SUBST_NOTMAKE. +AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) + +# Check how to create a tarball. -*- Autoconf -*- + +# Copyright (C) 2004, 2005, 2012 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# serial 2 + +# _AM_PROG_TAR(FORMAT) +# -------------------- +# Check how to create a tarball in format FORMAT. +# FORMAT should be one of `v7', `ustar', or `pax'. +# +# Substitute a variable $(am__tar) that is a command +# writing to stdout a FORMAT-tarball containing the directory +# $tardir. +# tardir=directory && $(am__tar) > result.tar +# +# Substitute a variable $(am__untar) that extract such +# a tarball read from stdin. +# $(am__untar) < result.tar +AC_DEFUN([_AM_PROG_TAR], +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], + [m4_case([$1], [ustar],, [pax],, + [m4_fatal([Unknown tar format])]) +AC_MSG_CHECKING([how to create a $1 tar archive]) +# Loop over all known methods to create a tar archive until one works. +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' +_am_tools=${am_cv_prog_tar_$1-$_am_tools} +# Do not fold the above two line into one, because Tru64 sh and +# Solaris sh will not grok spaces in the rhs of `-'. +for _am_tool in $_am_tools +do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; + do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi +done +rm -rf conftest.dir + +AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) +AC_MSG_RESULT([$am_cv_prog_tar_$1])]) +AC_SUBST([am__tar]) +AC_SUBST([am__untar]) +]) # _AM_PROG_TAR + +m4_include([acinclude.m4]) diff --git a/config.h.in b/config.h.in new file mode 100644 index 000000000..1f5a69b23 --- /dev/null +++ b/config.h.in @@ -0,0 +1,450 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Expanded binary directory */ +#undef BINDIR + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_ARPA_INET_H + +/* Define to 1 if you have the declaration of `backtrace', and to 0 if you + don't. */ +#undef HAVE_DECL_BACKTRACE + +/* Define to 1 if you have the declaration of `gnutls_fingerprint', and to 0 + if you don't. */ +#undef HAVE_DECL_GNUTLS_FINGERPRINT + +/* Define to 1 if you have the declaration of `MD5', and to 0 if you don't. */ +#undef HAVE_DECL_MD5 + +/* Define to 1 if you have the declaration of `round', and to 0 if you don't. + */ +#undef HAVE_DECL_ROUND + +/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ +#undef HAVE_DOPRNT + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GCRYPT_H + +/* Define to 1 if you have the `gethostbyname' function. */ +#undef HAVE_GETHOSTBYNAME + +/* Define to 1 if you have the `gethostname' function. */ +#undef HAVE_GETHOSTNAME + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the header file. */ +#undef HAVE_GLOB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GNUTLS_GNUTLS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_GNUTLS_OPENSSL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `ioctl' function. */ +#undef HAVE_IOCTL + +/* Define to 1 if you have the `ioctlsocket' function. */ +#undef HAVE_IOCTLSOCKET + +/* Define to 1 if you have the header file. */ +#undef HAVE_JPEGLIB_H + +/* Define to 1 if you have the `avcodec' library (-lavcodec). */ +#undef HAVE_LIBAVCODEC + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBAVCODEC_AVCODEC_H + +/* Define to 1 if you have the `avcore' library (-lavcore). */ +#undef HAVE_LIBAVCORE + +/* Define to 1 if you have the `avdevice' library (-lavdevice). */ +#undef HAVE_LIBAVDEVICE + +/* Define to 1 if you have the `avformat' library (-lavformat). */ +#undef HAVE_LIBAVFORMAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBAVFORMAT_AVFORMAT_H + +/* Define to 1 if you have the `avutil' library (-lavutil). */ +#undef HAVE_LIBAVUTIL + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBAVUTIL_AVUTIL_H + +/* Define to 1 if you have the `bz2' library (-lbz2). */ +#undef HAVE_LIBBZ2 + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +#undef HAVE_LIBCRYPTO + +/* Define to 1 if you have the `dl' library (-ldl). */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the `gcrypt' library (-lgcrypt). */ +#undef HAVE_LIBGCRYPT + +/* Define to 1 if you have the `gnutls' library (-lgnutls). */ +#undef HAVE_LIBGNUTLS + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#undef HAVE_LIBJPEG + +/* Define to 1 if you have the `mysqlclient' library (-lmysqlclient). */ +#undef HAVE_LIBMYSQLCLIENT + +/* Define to 1 if you have the `pcre' library (-lpcre). */ +#undef HAVE_LIBPCRE + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `swscale' library (-lswscale). */ +#undef HAVE_LIBSWSCALE + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIBSWSCALE_SWSCALE_H + +/* Define to 1 if you have the `x264' library (-lx264). */ +#undef HAVE_LIBX264 + +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_VIDEODEV2_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_LINUX_VIDEODEV_H + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#undef HAVE_MALLOC + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `memset' function. */ +#undef HAVE_MEMSET + +/* Define to 1 if you have the `mkdir' function. */ +#undef HAVE_MKDIR + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define to 1 if you have the `munmap' function. */ +#undef HAVE_MUNMAP + +/* Define to 1 if you have the header file. */ +#undef HAVE_MYSQL_MYSQL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETDB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_MD5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PCRE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_PCRE_PCRE_H + +/* Define to 1 if you have the `posix_memalign' function. */ +#undef HAVE_POSIX_MEMALIGN + +/* Define to 1 if you have the header file. */ +#undef HAVE_PTHREAD_H + +/* Define to 1 if you have the `putenv' function. */ +#undef HAVE_PUTENV + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `sendfile' function. */ +#undef HAVE_SENDFILE + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if the system has the type `siginfo_t'. */ +#undef HAVE_SIGINFO_T + +/* Define to 1 if you have the `sleep' function. */ +#undef HAVE_SLEEP + +/* Define to 1 if you have the `socket' function. */ +#undef HAVE_SOCKET + +/* Define to 1 if you have the `sqrt' function. */ +#undef HAVE_SQRT + +/* Define to 1 if `stat' has the bug that it succeeds when given the + zero-length file name argument. */ +#undef HAVE_STAT_EMPTY_STRING_BUG + +/* Define to 1 if stdbool.h conforms to C99. */ +#undef HAVE_STDBOOL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDDEF_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strcspn' function. */ +#undef HAVE_STRCSPN + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the `strncasecmp' function. */ +#undef HAVE_STRNCASECMP + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strsignal' function. */ +#undef HAVE_STRSIGNAL + +/* Define to 1 if you have the `strspn' function. */ +#undef HAVE_STRSPN + +/* Define to 1 if you have the `strstr' function. */ +#undef HAVE_STRSTR + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the `strtoull' function. */ +#undef HAVE_STRTOULL + +/* Define to 1 if the system has the type `struct sigcontext'. */ +#undef HAVE_STRUCT_SIGCONTEXT + +/* Define to 1 if `eip' is a member of `struct sigcontext'. */ +#undef HAVE_STRUCT_SIGCONTEXT_EIP + +/* Define to 1 if you have the `syscall' function. */ +#undef HAVE_SYSCALL + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSCALL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IOCTL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_IPC_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SENDFILE_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SHM_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_UN_H + +/* Define to 1 if the system has the type `ucontext_t'. */ +#undef HAVE_UCONTEXT_T + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `usleep' function. */ +#undef HAVE_USLEEP + +/* Define to 1 if you have the header file. */ +#undef HAVE_VALUES_H + +/* Define to 1 if you have the `vprintf' function. */ +#undef HAVE_VPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + +/* Define to 1 if the system has the type `_Bool'. */ +#undef HAVE__BOOL + +/* Expanded library directory */ +#undef LIBDIR + +/* Define to 1 if `lstat' dereferences a symlink specified with a trailing + slash. */ +#undef LSTAT_FOLLOWS_SLASHED_SYMLINK + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* Define to the type of arg 1 for `select'. */ +#undef SELECT_TYPE_ARG1 + +/* Define to the type of args 2, 3 and 4 for `select'. */ +#undef SELECT_TYPE_ARG234 + +/* Define to the type of arg 5 for `select'. */ +#undef SELECT_TYPE_ARG5 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Expanded configuration directory */ +#undef SYSCONFDIR + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Version number of package */ +#undef VERSION + +/* "Whether debug is switched off and compiled out" */ +#undef ZM_DBG_OFF + +/* "Whether to use mapped rather than shared memory" */ +#undef ZM_MEM_MAPPED + +/* "Whether crash tracing is switched off and compiled out" */ +#undef ZM_NO_CRASHTRACE + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `int' if doesn't define. */ +#undef gid_t + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* Define to rpl_malloc if the replacement function should be used. */ +#undef malloc + +/* Define to `int' if does not define. */ +#undef mode_t + +/* Define to `unsigned int' if does not define. */ +#undef size_t + +/* Define to `int' if doesn't define. */ +#undef uid_t diff --git a/configure b/configure new file mode 100755 index 000000000..98677df99 --- /dev/null +++ b/configure @@ -0,0 +1,11153 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for zm 1.25.0. +# +# Report bugs to . +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and +$0: http://www.zoneminder.com/forums/ - Please check FAQ +$0: first about your system, including any error possibly +$0: output before this message. Then install a modern +$0: shell, or manually run the script under such a shell if +$0: you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='zm' +PACKAGE_TARNAME='ZoneMinder' +PACKAGE_VERSION='1.25.0' +PACKAGE_STRING='zm 1.25.0' +PACKAGE_BUGREPORT='http://www.zoneminder.com/forums/ - Please check FAQ first' +PACKAGE_URL='http://www.zoneminder.com/downloads.html' + +ac_unique_file="src/zm.h" +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_header_list= +ac_subst_vars='am__EXEEXT_FALSE +am__EXEEXT_TRUE +LTLIBOBJS +EXTRA_PERL_LIB +PERL_MM_PARMS +ZM_CONFIG +SYSCONFDIR +ZM_PID +LIBDIR +BINDIR +PERL +ZM_PCRE +ZM_HAS_V4L +ZM_HAS_V4L2 +ZM_HAS_V4L1 +ALLOCA +ZM_HAS_GNUTLS +ZM_HAS_GNUTLS_OPENSSL +PATH_NETPBM +OPT_NETPBM +PATH_FFMPEG +OPT_FFMPEG +POW_LIB +LIBOBJS +EGREP +GREP +CXXCPP +RANLIB +LN_S +am__fastdepCC_FALSE +am__fastdepCC_TRUE +CCDEPMODE +ac_ct_CC +CFLAGS +CC +am__fastdepCXX_FALSE +am__fastdepCXX_TRUE +CXXDEPMODE +am__nodep +AMDEPBACKSLASH +AMDEP_FALSE +AMDEP_TRUE +am__quote +am__include +DEPDIR +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +ENABLE_MMAP +WEB_HOST +WEB_GROUP +WEB_USER +CGI_PREFIX +WEB_PREFIX +EXTRA_LIBS +FFMPEG_CFLAGS +FFMPEG_LIBS +FFMPEG_PREFIX +MYSQL_CFLAGS +MYSQL_LIBS +MYSQL_PREFIX +LIB_ARCH +ZM_LOGDIR +ZM_TMPDIR +ZM_RUNDIR +ZM_MYSQL_ENGINE +ZM_SSL_LIB +ZM_DB_PASS +ZM_DB_USER +ZM_DB_NAME +ZM_DB_HOST +TIME_BUILD +PATH_BUILD +am__untar +am__tar +AMTAR +am__leading_dot +SET_MAKE +AWK +mkdir_p +MKDIR_P +INSTALL_STRIP_PROGRAM +STRIP +install_sh +MAKEINFO +AUTOHEADER +AUTOMAKE +AUTOCONF +ACLOCAL +VERSION +PACKAGE +CYGPATH_W +am__isrc +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +with_libarch +with_mysql +with_ffmpeg +with_extralibs +with_webdir +with_cgidir +with_webuser +with_webgroup +with_webhost +enable_debug +enable_crashtrace +enable_mmap +enable_dependency_tracking +' + ac_precious_vars='build_alias +host_alias +target_alias +ZM_DB_HOST +ZM_DB_NAME +ZM_DB_USER +ZM_DB_PASS +ZM_SSL_LIB +ZM_MYSQL_ENGINE +ZM_RUNDIR +ZM_TMPDIR +ZM_LOGDIR +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CC +CFLAGS +CXXCPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures zm 1.25.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/ZoneMinder] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of zm 1.25.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-debug= enable or disable debug, default enabled + --enable-crashtrace= enable or disabled crash tracing, default enabled + --enable-mmap= enable or disabled mapped memory versus shared memory, default mapped + --disable-dependency-tracking speeds up one-time build + --enable-dependency-tracking do not reject slow dependency extractors + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-libarch= architecture library path to use, default lib + --with-mysql= prefix of MySQL installation, default /usr + --with-ffmpeg= prefix of ffmpeg root directory for libavcodec etc, default /usr + --with-extralibs="" string containing extra libraries to pass to link, default empty + --with-webdir= prefix of web directory + --with-cgidir= prefix of cgi directory + --with-webuser= name of web user, default apache + --with-webgroup= name of web group, default apache + --with-webhost= name of web hostname, default zm.local + +Some influential environment variables: + ZM_DB_HOST Hostname where ZoneMinder database located, default localhost + ZM_DB_NAME Name of ZoneMinder database, default zm + ZM_DB_USER Name of ZoneMinder database user, default zmuser + ZM_DB_PASS Password of ZoneMinder database user, default zmpass + ZM_SSL_LIB Library to use for ssl functions, default gnutls + ZM_MYSQL_ENGINE + MySQL engine to use with database, default MyISAM + ZM_RUNDIR Location of transient process files, default /var/run/zm + ZM_TMPDIR Location of temporary files, default /tmp/zm + ZM_LOGDIR Location of generated log files, default /var/log/zm + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CC C compiler command + CFLAGS C compiler flags + CXXCPP C++ preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +zm home page: . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +zm configure 1.25.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_check_type LINENO TYPE VAR INCLUDES +# --------------------------------------------- +# Tests whether TYPE exists after having included INCLUDES, setting cache +# variable VAR accordingly. +ac_fn_cxx_check_type () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_type + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES +# ------------------------------------------------------ +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_cxx_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_member + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ------------------------------------------------------------------------- ## +## Report this to http://www.zoneminder.com/forums/ - Please check FAQ first ## +## ------------------------------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_cxx_check_func LINENO FUNC VAR +# ------------------------------------ +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_cxx_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_func + +# ac_fn_cxx_check_decl LINENO SYMBOL VAR INCLUDES +# ----------------------------------------------- +# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR +# accordingly. +ac_fn_cxx_check_decl () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + as_decl_name=`echo $2|sed 's/ *(.*//'` + as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 +$as_echo_n "checking whether $as_decl_name is declared... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +#ifndef $as_decl_name +#ifdef __cplusplus + (void) $as_decl_use; +#else + (void) $as_decl_name; +#endif +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_decl +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by zm $as_me 1.25.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +as_fn_append ac_header_list " stdlib.h" +as_fn_append ac_header_list " unistd.h" +as_fn_append ac_header_list " sys/param.h" +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +am__api_version='1.11' + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 +$as_echo_n "checking whether build environment is sane... " >&6; } +# Just in case +sleep 1 +echo timestamp > conftest.file +# Reject unsafe characters in $srcdir or the absolute working directory +# name. Accept space and tab only in the latter. +am_lf=' +' +case `pwd` in + *[\\\"\#\$\&\'\`$am_lf]*) + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; +esac +case $srcdir in + *[\\\"\#\$\&\'\`$am_lf\ \ ]*) + as_fn_error $? "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; +esac + +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken +alias in your environment" "$LINENO" 5 + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + as_fn_error $? "newly created file is older than distributed files! +Check your system clock" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +if test x"${MISSING+set}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; + *) + MISSING="\${SHELL} $am_aux_dir/missing" ;; + esac +fi +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +if test x"${install_sh}" != xset; then + case $am_aux_dir in + *\ * | *\ *) + install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; + *) + install_sh="\${SHELL} $am_aux_dir/install-sh" + esac +fi + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 +$as_echo_n "checking for a thread-safe mkdir -p... " >&6; } +if test -z "$MKDIR_P"; then + if ${ac_cv_path_mkdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in mkdir gmkdir; do + for ac_exec_ext in '' $ac_executable_extensions; do + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue + case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( + 'mkdir (GNU coreutils) '* | \ + 'mkdir (coreutils) '* | \ + 'mkdir (fileutils) '4.1*) + ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext + break 3;; + esac + done + done + done +IFS=$as_save_IFS + +fi + + test -d ./--version && rmdir ./--version + if test "${ac_cv_path_mkdir+set}" = set; then + MKDIR_P="$ac_cv_path_mkdir -p" + else + # As a last resort, use the slow shell script. Don't cache a + # value for MKDIR_P within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + MKDIR_P="$ac_install_sh -d" + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 +$as_echo "$MKDIR_P" >&6; } + +mkdir_p="$MKDIR_P" +case $mkdir_p in + [\\/$]* | ?:[\\/]*) ;; + */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; +esac + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + +rm -rf .tst 2>/dev/null +mkdir .tst 2>/dev/null +if test -d .tst; then + am__leading_dot=. +else + am__leading_dot=_ +fi +rmdir .tst 2>/dev/null + +if test "`cd $srcdir && pwd`" != "`pwd`"; then + # Use -I$(srcdir) only when $(srcdir) != ., so that make's output + # is not polluted with repeated "-I." + am__isrc=' -I$(srcdir)' + # test to see if srcdir already configured + if test -f $srcdir/config.status; then + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + fi +fi + +# test whether we have cygpath +if test -z "$CYGPATH_W"; then + if (cygpath --version) >/dev/null 2>/dev/null; then + CYGPATH_W='cygpath -w' + else + CYGPATH_W=echo + fi +fi + + +# Define the identity of the package. + PACKAGE='ZoneMinder' + VERSION='1.25.0' + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' + + + + + + +ac_config_headers="$ac_config_headers config.h" + + +PATH_BUILD=`pwd` + +TIME_BUILD=`date +'%s'` + + + + + + + + + + + + +if test "$ZM_DB_HOST" == ""; then + ZM_DB_HOST=localhost + +fi +if test "$ZM_DB_NAME" == ""; then + ZM_DB_NAME=zm + +fi +if test "$ZM_DB_USER" == ""; then + ZM_DB_USER=zmuser + +fi +if test "$ZM_DB_PASS" == ""; then + ZM_DB_PASS=zmpass + +fi +if test "$ZM_SSL_LIB" == ""; then + ZM_SSL_LIB=gnutls + +fi +if test "$ZM_MYSQL_ENGINE" == ""; then + ZM_MYSQL_ENGINE=MyISAM + +fi +if test "$ZM_RUNDIR" == ""; then + ZM_RUNDIR=/var/run/zm + +fi +if test "$ZM_TMPDIR" == ""; then + ZM_TMPDIR=/tmp/zm + +fi +if test "$ZM_LOGDIR" == ""; then + ZM_LOGDIR=/var/log/zm + +fi + +LIB_ARCH=lib + +# Check whether --with-libarch was given. +if test "${with_libarch+set}" = set; then : + withval=$with_libarch; LIB_ARCH=$with_libarch +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-libarch option. + This tells configure where to find architecture specific libraries. + The default of 'lib' is usually ok but 64 bit machines may require lib64. + e.g. --with-libarch=lib or --with-libarch=lib64" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-libarch option. + This tells configure where to find architecture specific libraries. + The default of 'lib' is usually ok but 64 bit machines may require lib64. + e.g. --with-libarch=lib or --with-libarch=lib64" >&2;} + +fi + + + +MYSQL_PREFIX=/usr + +# Check whether --with-mysql was given. +if test "${with_mysql+set}" = set; then : + withval=$with_mysql; MYSQL_PREFIX=$with_mysql +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-mysql option. + This tells configure where to find the MySql C library and headers if configure cannot + locate them automatically. + e.g. --with-mysql=/usr/local or --with-mysql=/usr" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-mysql option. + This tells configure where to find the MySql C library and headers if configure cannot + locate them automatically. + e.g. --with-mysql=/usr/local or --with-mysql=/usr" >&2;} + +fi + + +MYSQL_LIBS="-L${MYSQL_PREFIX}/${LIB_ARCH}/mysql" +MYSQL_CFLAGS="-I${MYSQL_PREFIX}/include" + + + +LDFLAGS="${MYSQL_LIBS} $LDFLAGS" + +FFMPEG_PREFIX=/usr + +# Check whether --with-ffmpeg was given. +if test "${with_ffmpeg+set}" = set; then : + withval=$with_ffmpeg; FFMPEG_PREFIX=$with_ffmpeg +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-ffmpeg option. + This tells configure where to find the ffmpeg root directory within which are the libavcodec + and libavformat files that can be used to build true MPEG streaming into ZoneMinder. Ensure that + your copy of ffmpeg has installed libraries as well as binaries (use 'make installlib'). If you + are using a local install of ffmpeg you may have to remove or rename a previous real installation + as the headers and libraries from that will probably be picked up before your local copy. + e.g. --with-ffmpeg=/usr/local" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-ffmpeg option. + This tells configure where to find the ffmpeg root directory within which are the libavcodec + and libavformat files that can be used to build true MPEG streaming into ZoneMinder. Ensure that + your copy of ffmpeg has installed libraries as well as binaries (use 'make installlib'). If you + are using a local install of ffmpeg you may have to remove or rename a previous real installation + as the headers and libraries from that will probably be picked up before your local copy. + e.g. --with-ffmpeg=/usr/local" >&2;} + +fi + + +FFMPEG_LIBS="-L${FFMPEG_PREFIX}/${LIB_ARCH}" +FFMPEG_CFLAGS="-I${FFMPEG_PREFIX}/include -D__STDC_CONSTANT_MACROS" + + + +LDFLAGS="${FFMPEG_LIBS} $LDFLAGS" +CFLAGS="${FFMPEG_CFLAGS} $CFLAGS" +CPPFLAGS="${FFMPEG_CFLAGS} $CPPFLAGS" + +EXTRA_LIBS= + +# Check whether --with-extralibs was given. +if test "${with_extralibs+set}" = set; then : + withval=$with_extralibs; EXTRA_LIBS=$with_extralibs +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-extralibs option. + Ordinarily you will need to use this option only when your copy of ffmpeg has been built + with support for additional formats and you would use this option to detail which additional + libraries ffmpeg was built with so that it is able to link successfully with ZoneMinder. + You will need to wrap this option in quotes if it contains any spaces. + e.g. --with-extralibs=\"-lmp3lame\"" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-extralibs option. + Ordinarily you will need to use this option only when your copy of ffmpeg has been built + with support for additional formats and you would use this option to detail which additional + libraries ffmpeg was built with so that it is able to link successfully with ZoneMinder. + You will need to wrap this option in quotes if it contains any spaces. + e.g. --with-extralibs=\"-lmp3lame\"" >&2;} + +fi + + + +LDFLAGS="$LDFLAGS ${EXTRA_LIBS}" + + +# Check whether --with-webdir was given. +if test "${with_webdir+set}" = set; then : + withval=$with_webdir; WEB_PREFIX=$with_webdir +else + as_fn_error $? "You must call configure with the --with-webdir option. + This tells configure where to install PHP and web files and scripts. + e.g. --with-webdir=/var/www/html or --with-webdir=/www/vhtdocs/" "$LINENO" 5 + +fi + + + + +# Check whether --with-cgidir was given. +if test "${with_cgidir+set}" = set; then : + withval=$with_cgidir; CGI_PREFIX=$with_cgidir +else + as_fn_error $? "You must call configure with the --with-cgidir option. + This tells configure where to install cgi files and scripts. + e.g. --with-cgidir=/var/www/cgi-bin or --with-webdir=/www/vhtdocs//cgi-bin" "$LINENO" 5 + +fi + + + +WEB_USER=apache + +# Check whether --with-webuser was given. +if test "${with_webuser+set}" = set; then : + withval=$with_webuser; WEB_USER=$with_webuser +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-webuser option. + This tells configure what the user name of the web user is if it is not the default of 'apache'. + e.g. --with-webuser=apache or --with-webuser=web" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-webuser option. + This tells configure what the user name of the web user is if it is not the default of 'apache'. + e.g. --with-webuser=apache or --with-webuser=web" >&2;} + +fi + + + +WEB_GROUP=apache + +# Check whether --with-webgroup was given. +if test "${with_webgroup+set}" = set; then : + withval=$with_webgroup; WEB_GROUP=$with_webgroup +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-webgroup option. + This tells configure what the group name of the web group is if it is not the default of 'apache'. + e.g. --with-webgroup=apache or --with-webgroup=web" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-webgroup option. + This tells configure what the group name of the web group is if it is not the default of 'apache'. + e.g. --with-webgroup=apache or --with-webgroup=web" >&2;} + +fi + + + +WEB_HOST=zm.local + +# Check whether --with-webhost was given. +if test "${with_webhost+set}" = set; then : + withval=$with_webhost; WEB_HOST=$with_webhost +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --with-webhost option. + This tells configure what the host name is for name based virtual hosting. This is only used to populate the sample web/zmHttpd.conf file. + e.g. --with-webhost=zm.localdomain" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --with-webhost option. + This tells configure what the host name is for name based virtual hosting. This is only used to populate the sample web/zmHttpd.conf file. + e.g. --with-webhost=zm.localdomain" >&2;} + +fi + + + +ENABLE_DEBUG=yes +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; ENABLE_DEBUG=$enable_debug +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --enable-debug= or --disable-debug option. + This tells configure whether to compile ZoneMinder with debug included. Although debug is included + by default it is not output unless explicitly switched on elsewhere. These checks may induce a + small penalty on performance and if you are after squeezing the maximum possible performance out + of ZoneMinder you may use this switch to prevent debug from being compiled in. + e.g. --enable-debug=yes or --disable-debug" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --enable-debug= or --disable-debug option. + This tells configure whether to compile ZoneMinder with debug included. Although debug is included + by default it is not output unless explicitly switched on elsewhere. These checks may induce a + small penalty on performance and if you are after squeezing the maximum possible performance out + of ZoneMinder you may use this switch to prevent debug from being compiled in. + e.g. --enable-debug=yes or --disable-debug" >&2;} + +fi + +if test "$ENABLE_DEBUG" != "yes"; then + +$as_echo "#define ZM_DBG_OFF 1" >>confdefs.h + +fi + +ENABLE_CRASHTRACE=yes +# Check whether --enable-crashtrace was given. +if test "${enable_crashtrace+set}" = set; then : + enableval=$enable_crashtrace; ENABLE_CRASHTRACE=$enable_crashtrace +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --enable-crashtrace= or --disable-crashtrace option. + This tells configure whether to compile ZoneMinder with crash tracing included. This allows a + dump of the stack trace when a ZoneMinder binary crashes or is killed by an unexpected signal. + Although this should work on most systems it does rely on un(or loosely) documented features and + so should be regarded as experimental. If you experience problems compiling zm_signal.cpp or + ZoneMinder binaries fail to shut down correctly then you should probably disable this feature. + e.g. --enable-crashtrace=yes or --disable-crashtrace" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --enable-crashtrace= or --disable-crashtrace option. + This tells configure whether to compile ZoneMinder with crash tracing included. This allows a + dump of the stack trace when a ZoneMinder binary crashes or is killed by an unexpected signal. + Although this should work on most systems it does rely on un(or loosely) documented features and + so should be regarded as experimental. If you experience problems compiling zm_signal.cpp or + ZoneMinder binaries fail to shut down correctly then you should probably disable this feature. + e.g. --enable-crashtrace=yes or --disable-crashtrace" >&2;} + +fi + +if test "$ENABLE_CRASHTRACE" != "yes"; then + +$as_echo "#define ZM_NO_CRASHTRACE 1" >>confdefs.h + +fi + +ENABLE_MMAP=yes +# Check whether --enable-mmap was given. +if test "${enable_mmap+set}" = set; then : + enableval=$enable_mmap; ENABLE_MMAP=$enable_mmap +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You can call configure with the --enable-mmap= or --disable-mmap option. + This tells configure whether to compile ZoneMinder with mmap support rather than IPC shared + memory. This is a feature that uses memory mapped into files which all processes can share. + Memory mapping requires less configuration and is more flexible than shared memory but may + slow down your system unless the mapped files are configured to reside on a fast or RAM based + filesystem which will normally be the case by default. + e.g. --enable-mmap=yes or --disable-mmap" >&5 +$as_echo "$as_me: WARNING: You can call configure with the --enable-mmap= or --disable-mmap option. + This tells configure whether to compile ZoneMinder with mmap support rather than IPC shared + memory. This is a feature that uses memory mapped into files which all processes can share. + Memory mapping requires less configuration and is more flexible than shared memory but may + slow down your system unless the mapped files are configured to reside on a fast or RAM based + filesystem which will normally be the case by default. + e.g. --enable-mmap=yes or --disable-mmap" >&2;} + +fi + +if test "$ENABLE_MMAP" == "yes"; then + +$as_echo "#define ZM_MEM_MAPPED 1" >>confdefs.h + +else + +$as_echo "#define ZM_MEM_MAPPED 0" >>confdefs.h + +fi + + +# Compiler +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +# Checks for programs. +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +DEPDIR="${am__leading_dot}deps" + +ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +am__doit: + @echo this is the am__doit target +.PHONY: am__doit +END +# If we don't find an include directive, just comment out the code. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 +$as_echo_n "checking for style of include used by $am_make... " >&6; } +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# Ignore all kinds of additional output from `make'. +case `$am_make -s -f confmf 2> /dev/null` in #( +*the\ am__doit\ target*) + am__include=include + am__quote= + _am_result=GNU + ;; +esac +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + case `$am_make -s -f confmf 2> /dev/null` in #( + *the\ am__doit\ target*) + am__include=.include + am__quote="\"" + _am_result=BSD + ;; + esac +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 +$as_echo "$_am_result" >&6; } +rm -f confinc confmf + +# Check whether --enable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then : + enableval=$enable_dependency_tracking; +fi + +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' + am__nodep='_no' +fi + if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + +depcc="$CXX" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CXX_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then + am__fastdepCXX_TRUE= + am__fastdepCXX_FALSE='#' +else + am__fastdepCXX_TRUE='#' + am__fastdepCXX_FALSE= +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +depcc="$CC" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CC_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + case " $depcc " in #( + *\ -arch\ *\ -arch\ *) am__universal=true ;; + esac + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with + # Solaris 8's {/usr,}/bin/sh. + touch sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok `-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then + am__fastdepCC_TRUE= + am__fastdepCC_FALSE='#' +else + am__fastdepCC_TRUE='#' + am__fastdepCC_FALSE= +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } +set x ${MAKE-make} +ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat >conftest.make <<\_ACEOF +SHELL = /bin/sh +all: + @echo '@@@%%%=$(MAKE)=@@@%%%' +_ACEOF +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. +case `${MAKE-make} -f conftest.make 2>/dev/null` in + *@@@%%%=?*=@@@%%%*) + eval ac_cv_prog_make_${ac_make}_set=yes;; + *) + eval ac_cv_prog_make_${ac_make}_set=no;; +esac +rm -f conftest.make +fi +if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SET_MAKE= +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SET_MAKE="MAKE=${MAKE-make}" +fi + + +# Checks for typedefs, structures, and compiler characteristics. + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 +$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } +if ${ac_cv_header_stdbool_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #ifndef bool + "error: bool is not defined" + #endif + #ifndef false + "error: false is not defined" + #endif + #if false + "error: false is not 0" + #endif + #ifndef true + "error: true is not defined" + #endif + #if true != 1 + "error: true is not 1" + #endif + #ifndef __bool_true_false_are_defined + "error: __bool_true_false_are_defined is not defined" + #endif + + struct s { _Bool s: 1; _Bool t; } s; + + char a[true == 1 ? 1 : -1]; + char b[false == 0 ? 1 : -1]; + char c[__bool_true_false_are_defined == 1 ? 1 : -1]; + char d[(bool) 0.5 == true ? 1 : -1]; + /* See body of main program for 'e'. */ + char f[(_Bool) 0.0 == false ? 1 : -1]; + char g[true]; + char h[sizeof (_Bool)]; + char i[sizeof s.t]; + enum { j = false, k = true, l = false * true, m = true * 256 }; + /* The following fails for + HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ + _Bool n[m]; + char o[sizeof n == m * sizeof n[0] ? 1 : -1]; + char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; + /* Catch a bug in an HP-UX C compiler. See + http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html + http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html + */ + _Bool q = true; + _Bool *pq = &q; + +int +main () +{ + + bool e = &s; + *pq |= q; + *pq |= ! q; + /* Refer to every declared value, to avoid compiler optimizations. */ + return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + + !m + !n + !o + !p + !q + !pq); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdbool_h=yes +else + ac_cv_header_stdbool_h=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 +$as_echo "$ac_cv_header_stdbool_h" >&6; } + ac_fn_cxx_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" +if test "x$ac_cv_type__Bool" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE__BOOL 1 +_ACEOF + + +fi + + +if test $ac_cv_header_stdbool_h = yes; then + +$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#ifndef __cplusplus + /* Ultrix mips cc rejects this sort of thing. */ + typedef int charset[2]; + const charset cs = { 0, 0 }; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 +$as_echo_n "checking for uid_t in sys/types.h... " >&6; } +if ${ac_cv_type_uid_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uid_t" >/dev/null 2>&1; then : + ac_cv_type_uid_t=yes +else + ac_cv_type_uid_t=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 +$as_echo "$ac_cv_type_uid_t" >&6; } +if test $ac_cv_type_uid_t = no; then + +$as_echo "#define uid_t int" >>confdefs.h + + +$as_echo "#define gid_t int" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + +ac_fn_cxx_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" +if test "x$ac_cv_type_mode_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define mode_t int +_ACEOF + +fi + +ac_fn_cxx_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 +$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } +if ${ac_cv_struct_tm+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +struct tm tm; + int *p = &tm.tm_sec; + return !p; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_struct_tm=time.h +else + ac_cv_struct_tm=sys/time.h +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5 +$as_echo "$ac_cv_struct_tm" >&6; } +if test $ac_cv_struct_tm = sys/time.h; then + +$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 +$as_echo_n "checking return type of signal handlers... " >&6; } +if ${ac_cv_type_signal+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +int +main () +{ +return *(signal (0, 0)) (0) == 1; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_type_signal=int +else + ac_cv_type_signal=void +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 +$as_echo "$ac_cv_type_signal" >&6; } + +cat >>confdefs.h <<_ACEOF +#define RETSIGTYPE $ac_cv_type_signal +_ACEOF + + + +ac_fn_cxx_check_type "$LINENO" "siginfo_t" "ac_cv_type_siginfo_t" "#include +" +if test "x$ac_cv_type_siginfo_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_SIGINFO_T 1 +_ACEOF + + +fi + +ac_fn_cxx_check_type "$LINENO" "struct sigcontext" "ac_cv_type_struct_sigcontext" "#include +" +if test "x$ac_cv_type_struct_sigcontext" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SIGCONTEXT 1 +_ACEOF + + +fi + +ac_fn_cxx_check_member "$LINENO" "struct sigcontext" "eip" "ac_cv_member_struct_sigcontext_eip" "#include +" +if test "x$ac_cv_member_struct_sigcontext_eip" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_SIGCONTEXT_EIP 1 +_ACEOF + + +fi + +ac_fn_cxx_check_type "$LINENO" "ucontext_t" "ac_cv_type_ucontext_t" "#include +" +if test "x$ac_cv_type_ucontext_t" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_UCONTEXT_T 1 +_ACEOF + + +fi + + +# Checks for library functions. +if test $ac_cv_c_compiler_gnu = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC needs -traditional" >&5 +$as_echo_n "checking whether $CC needs -traditional... " >&6; } +if ${ac_cv_prog_gcc_traditional+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_pattern="Autoconf.*'x'" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then : + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_gcc_traditional" >&5 +$as_echo "$ac_cv_prog_gcc_traditional" >&6; } + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +for ac_header in stdlib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" +if test "x$ac_cv_header_stdlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STDLIB_H 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 +$as_echo_n "checking for GNU libc compatible malloc... " >&6; } +if ${ac_cv_func_malloc_0_nonnull+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_malloc_0_nonnull=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined STDC_HEADERS || defined HAVE_STDLIB_H +# include +#else +char *malloc (); +#endif + +int +main () +{ +return ! malloc (0); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_func_malloc_0_nonnull=yes +else + ac_cv_func_malloc_0_nonnull=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } +if test $ac_cv_func_malloc_0_nonnull = yes; then : + +$as_echo "#define HAVE_MALLOC 1" >>confdefs.h + +else + $as_echo "#define HAVE_MALLOC 0" >>confdefs.h + + case " $LIBOBJS " in + *" malloc.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS malloc.$ac_objext" + ;; +esac + + +$as_echo "#define malloc rpl_malloc" >>confdefs.h + +fi + + + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + +for ac_func in getpagesize +do : + ac_fn_cxx_check_func "$LINENO" "getpagesize" "ac_cv_func_getpagesize" +if test "x$ac_cv_func_getpagesize" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETPAGESIZE 1 +_ACEOF + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mmap" >&5 +$as_echo_n "checking for working mmap... " >&6; } +if ${ac_cv_func_mmap_fixed_mapped+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_mmap_fixed_mapped=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +/* malloc might have been renamed as rpl_malloc. */ +#undef malloc + +/* Thanks to Mike Haertel and Jim Avera for this test. + Here is a matrix of mmap possibilities: + mmap private not fixed + mmap private fixed at somewhere currently unmapped + mmap private fixed at somewhere already mapped + mmap shared not fixed + mmap shared fixed at somewhere currently unmapped + mmap shared fixed at somewhere already mapped + For private mappings, we should verify that changes cannot be read() + back from the file, nor mmap's back from the file at a different + address. (There have been systems where private was not correctly + implemented like the infamous i386 svr4.0, and systems where the + VM page cache was not coherent with the file system buffer cache + like early versions of FreeBSD and possibly contemporary NetBSD.) + For shared mappings, we should conversely verify that changes get + propagated back to all the places they're supposed to be. + + Grep wants private fixed already mapped. + The main things grep needs to know about mmap are: + * does it exist and is it safe to write into the mmap'd area + * how to use it (BSD variants) */ + +#include +#include + +#if !defined STDC_HEADERS && !defined HAVE_STDLIB_H +char *malloc (); +#endif + +/* This mess was copied from the GNU getpagesize.h. */ +#ifndef HAVE_GETPAGESIZE +# ifdef _SC_PAGESIZE +# define getpagesize() sysconf(_SC_PAGESIZE) +# else /* no _SC_PAGESIZE */ +# ifdef HAVE_SYS_PARAM_H +# include +# ifdef EXEC_PAGESIZE +# define getpagesize() EXEC_PAGESIZE +# else /* no EXEC_PAGESIZE */ +# ifdef NBPG +# define getpagesize() NBPG * CLSIZE +# ifndef CLSIZE +# define CLSIZE 1 +# endif /* no CLSIZE */ +# else /* no NBPG */ +# ifdef NBPC +# define getpagesize() NBPC +# else /* no NBPC */ +# ifdef PAGESIZE +# define getpagesize() PAGESIZE +# endif /* PAGESIZE */ +# endif /* no NBPC */ +# endif /* no NBPG */ +# endif /* no EXEC_PAGESIZE */ +# else /* no HAVE_SYS_PARAM_H */ +# define getpagesize() 8192 /* punt totally */ +# endif /* no HAVE_SYS_PARAM_H */ +# endif /* no _SC_PAGESIZE */ + +#endif /* no HAVE_GETPAGESIZE */ + +int +main () +{ + char *data, *data2, *data3; + const char *cdata2; + int i, pagesize; + int fd, fd2; + + pagesize = getpagesize (); + + /* First, make a file with some known garbage in it. */ + data = (char *) malloc (pagesize); + if (!data) + return 1; + for (i = 0; i < pagesize; ++i) + *(data + i) = rand (); + umask (0); + fd = creat ("conftest.mmap", 0600); + if (fd < 0) + return 2; + if (write (fd, data, pagesize) != pagesize) + return 3; + close (fd); + + /* Next, check that the tail of a page is zero-filled. File must have + non-zero length, otherwise we risk SIGBUS for entire page. */ + fd2 = open ("conftest.txt", O_RDWR | O_CREAT | O_TRUNC, 0600); + if (fd2 < 0) + return 4; + cdata2 = ""; + if (write (fd2, cdata2, 1) != 1) + return 5; + data2 = (char *) mmap (0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0L); + if (data2 == MAP_FAILED) + return 6; + for (i = 0; i < pagesize; ++i) + if (*(data2 + i)) + return 7; + close (fd2); + if (munmap (data2, pagesize)) + return 8; + + /* Next, try to mmap the file at a fixed address which already has + something else allocated at it. If we can, also make sure that + we see the same garbage. */ + fd = open ("conftest.mmap", O_RDWR); + if (fd < 0) + return 9; + if (data2 != mmap (data2, pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_FIXED, fd, 0L)) + return 10; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data2 + i)) + return 11; + + /* Finally, make sure that changes to the mapped area do not + percolate back to the file as seen by read(). (This is a bug on + some variants of i386 svr4.0.) */ + for (i = 0; i < pagesize; ++i) + *(data2 + i) = *(data2 + i) + 1; + data3 = (char *) malloc (pagesize); + if (!data3) + return 12; + if (read (fd, data3, pagesize) != pagesize) + return 13; + for (i = 0; i < pagesize; ++i) + if (*(data + i) != *(data3 + i)) + return 14; + close (fd); + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_func_mmap_fixed_mapped=yes +else + ac_cv_func_mmap_fixed_mapped=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_mmap_fixed_mapped" >&5 +$as_echo "$ac_cv_func_mmap_fixed_mapped" >&6; } +if test $ac_cv_func_mmap_fixed_mapped = yes; then + +$as_echo "#define HAVE_MMAP 1" >>confdefs.h + +fi +rm -f conftest.mmap conftest.txt + +for ac_header in sys/select.h sys/socket.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking types of arguments for select" >&5 +$as_echo_n "checking types of arguments for select... " >&6; } +if ${ac_cv_func_select_args+:} false; then : + $as_echo_n "(cached) " >&6 +else + for ac_arg234 in 'fd_set *' 'int *' 'void *'; do + for ac_arg1 in 'int' 'size_t' 'unsigned long int' 'unsigned int'; do + for ac_arg5 in 'struct timeval *' 'const struct timeval *'; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#ifdef HAVE_SYS_SOCKET_H +# include +#endif + +int +main () +{ +extern int select ($ac_arg1, + $ac_arg234, $ac_arg234, $ac_arg234, + $ac_arg5); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_func_select_args="$ac_arg1,$ac_arg234,$ac_arg5"; break 3 +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done + done +done +# Provide a safe default value. +: "${ac_cv_func_select_args=int,int *,struct timeval *}" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_select_args" >&5 +$as_echo "$ac_cv_func_select_args" >&6; } +ac_save_IFS=$IFS; IFS=',' +set dummy `echo "$ac_cv_func_select_args" | sed 's/\*/\*/g'` +IFS=$ac_save_IFS +shift + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG1 $1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG234 ($2) +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define SELECT_TYPE_ARG5 ($3) +_ACEOF + +rm -f conftest* + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether lstat correctly handles trailing slash" >&5 +$as_echo_n "checking whether lstat correctly handles trailing slash... " >&6; } +if ${ac_cv_func_lstat_dereferences_slashed_symlink+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f conftest.sym conftest.file +echo >conftest.file +if test "$as_ln_s" = "ln -s" && ln -s conftest.file conftest.sym; then + if test "$cross_compiling" = yes; then : + ac_cv_func_lstat_dereferences_slashed_symlink=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + /* Linux will dereference the symlink and fail, as required by POSIX. + That is better in the sense that it means we will not + have to compile and use the lstat wrapper. */ + return lstat ("conftest.sym/", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_func_lstat_dereferences_slashed_symlink=yes +else + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +else + # If the `ln -s' command failed, then we probably don't even + # have an lstat function. + ac_cv_func_lstat_dereferences_slashed_symlink=no +fi +rm -f conftest.sym conftest.file + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_lstat_dereferences_slashed_symlink" >&5 +$as_echo "$ac_cv_func_lstat_dereferences_slashed_symlink" >&6; } + +test $ac_cv_func_lstat_dereferences_slashed_symlink = yes && + +cat >>confdefs.h <<_ACEOF +#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 +_ACEOF + + +if test "x$ac_cv_func_lstat_dereferences_slashed_symlink" = xno; then + case " $LIBOBJS " in + *" lstat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS lstat.$ac_objext" + ;; +esac + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat accepts an empty string" >&5 +$as_echo_n "checking whether stat accepts an empty string... " >&6; } +if ${ac_cv_func_stat_empty_string_bug+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_stat_empty_string_bug=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +main () +{ +struct stat sbuf; + return stat ("", &sbuf) == 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_func_stat_empty_string_bug=no +else + ac_cv_func_stat_empty_string_bug=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_stat_empty_string_bug" >&5 +$as_echo "$ac_cv_func_stat_empty_string_bug" >&6; } +if test $ac_cv_func_stat_empty_string_bug = yes; then + case " $LIBOBJS " in + *" stat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS stat.$ac_objext" + ;; +esac + + +cat >>confdefs.h <<_ACEOF +#define HAVE_STAT_EMPTY_STRING_BUG 1 +_ACEOF + +fi + +for ac_func in strftime +do : + ac_fn_cxx_check_func "$LINENO" "strftime" "ac_cv_func_strftime" +if test "x$ac_cv_func_strftime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRFTIME 1 +_ACEOF + +else + # strftime is in -lintl on SCO UNIX. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for strftime in -lintl" >&5 +$as_echo_n "checking for strftime in -lintl... " >&6; } +if ${ac_cv_lib_intl_strftime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lintl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char strftime (); +int +main () +{ +return strftime (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_intl_strftime=yes +else + ac_cv_lib_intl_strftime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_strftime" >&5 +$as_echo "$ac_cv_lib_intl_strftime" >&6; } +if test "x$ac_cv_lib_intl_strftime" = xyes; then : + $as_echo "#define HAVE_STRFTIME 1" >>confdefs.h + +LIBS="-lintl $LIBS" +fi + +fi +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strtod" >&5 +$as_echo_n "checking for working strtod... " >&6; } +if ${ac_cv_func_strtod+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_func_strtod=no +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +$ac_includes_default +#ifndef strtod +double strtod (); +#endif +int +main() +{ + { + /* Some versions of Linux strtod mis-parse strings with leading '+'. */ + char *string = " +69"; + char *term; + double value; + value = strtod (string, &term); + if (value != 69 || term != (string + 4)) + return 1; + } + + { + /* Under Solaris 2.4, strtod returns the wrong value for the + terminating character under some conditions. */ + char *string = "NaN"; + char *term; + strtod (string, &term); + if (term != string && *(term - 1) == 0) + return 1; + } + return 0; +} + +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_func_strtod=yes +else + ac_cv_func_strtod=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_strtod" >&5 +$as_echo "$ac_cv_func_strtod" >&6; } +if test $ac_cv_func_strtod = no; then + case " $LIBOBJS " in + *" strtod.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strtod.$ac_objext" + ;; +esac + +ac_fn_cxx_check_func "$LINENO" "pow" "ac_cv_func_pow" +if test "x$ac_cv_func_pow" = xyes; then : + +fi + +if test $ac_cv_func_pow = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 +$as_echo_n "checking for pow in -lm... " >&6; } +if ${ac_cv_lib_m_pow+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pow (); +int +main () +{ +return pow (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_m_pow=yes +else + ac_cv_lib_m_pow=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 +$as_echo "$ac_cv_lib_m_pow" >&6; } +if test "x$ac_cv_lib_m_pow" = xyes; then : + POW_LIB=-lm +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find library containing definition of pow" >&5 +$as_echo "$as_me: WARNING: cannot find library containing definition of pow" >&2;} +fi + +fi + +fi + +for ac_func in vprintf +do : + ac_fn_cxx_check_func "$LINENO" "vprintf" "ac_cv_func_vprintf" +if test "x$ac_cv_func_vprintf" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_VPRINTF 1 +_ACEOF + +ac_fn_cxx_check_func "$LINENO" "_doprnt" "ac_cv_func__doprnt" +if test "x$ac_cv_func__doprnt" = xyes; then : + +$as_echo "#define HAVE_DOPRNT 1" >>confdefs.h + +fi + +fi +done + + +for ac_func in gethostbyname gethostname gettimeofday memmove memset mkdir munmap posix_memalign putenv select sendfile socket sqrt strcasecmp strchr strcspn strerror strncasecmp strrchr strsignal strspn strstr strtol strtoull +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + +for ac_func in syscall sleep usleep ioctl ioctlsocket sigaction +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Other programs +# Extract the first word of "ffmpeg", so it can be a program name with args. +set dummy ffmpeg; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OPT_FFMPEG+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OPT_FFMPEG"; then + ac_cv_prog_OPT_FFMPEG="$OPT_FFMPEG" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OPT_FFMPEG="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_OPT_FFMPEG" && ac_cv_prog_OPT_FFMPEG="no" +fi +fi +OPT_FFMPEG=$ac_cv_prog_OPT_FFMPEG +if test -n "$OPT_FFMPEG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPT_FFMPEG" >&5 +$as_echo "$OPT_FFMPEG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "ffmpeg", so it can be a program name with args. +set dummy ffmpeg; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_FFMPEG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PATH_FFMPEG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PATH_FFMPEG="$PATH_FFMPEG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATH_FFMPEG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PATH_FFMPEG=$ac_cv_path_PATH_FFMPEG +if test -n "$PATH_FFMPEG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_FFMPEG" >&5 +$as_echo "$PATH_FFMPEG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "pnmscale", so it can be a program name with args. +set dummy pnmscale; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OPT_NETPBM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OPT_NETPBM"; then + ac_cv_prog_OPT_NETPBM="$OPT_NETPBM" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OPT_NETPBM="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_prog_OPT_NETPBM" && ac_cv_prog_OPT_NETPBM="no" +fi +fi +OPT_NETPBM=$ac_cv_prog_OPT_NETPBM +if test -n "$OPT_NETPBM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPT_NETPBM" >&5 +$as_echo "$OPT_NETPBM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "pnmscale", so it can be a program name with args. +set dummy pnmscale; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PATH_NETPBM+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PATH_NETPBM in + [\\/]* | ?:[\\/]*) + ac_cv_path_PATH_NETPBM="$PATH_NETPBM" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PATH_NETPBM="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PATH_NETPBM=$ac_cv_path_PATH_NETPBM +if test -n "$PATH_NETPBM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PATH_NETPBM" >&5 +$as_echo "$PATH_NETPBM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test "$OPT_NETPBM" == "yes"; then +PATH_NETPBM=`dirname $PATH_NETPBM` +fi + +# Checks for libraries. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mysql_init in -lmysqlclient" >&5 +$as_echo_n "checking for mysql_init in -lmysqlclient... " >&6; } +if ${ac_cv_lib_mysqlclient_mysql_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lmysqlclient $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char mysql_init (); +int +main () +{ +return mysql_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_mysqlclient_mysql_init=yes +else + ac_cv_lib_mysqlclient_mysql_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mysqlclient_mysql_init" >&5 +$as_echo "$ac_cv_lib_mysqlclient_mysql_init" >&6; } +if test "x$ac_cv_lib_mysqlclient_mysql_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBMYSQLCLIENT 1 +_ACEOF + + LIBS="-lmysqlclient $LIBS" + +else + as_fn_error $? "zm requires libmysqlclient.a" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for jpeg_start_compress in -ljpeg" >&5 +$as_echo_n "checking for jpeg_start_compress in -ljpeg... " >&6; } +if ${ac_cv_lib_jpeg_jpeg_start_compress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ljpeg $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char jpeg_start_compress (); +int +main () +{ +return jpeg_start_compress (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_jpeg_jpeg_start_compress=yes +else + ac_cv_lib_jpeg_jpeg_start_compress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jpeg_jpeg_start_compress" >&5 +$as_echo "$ac_cv_lib_jpeg_jpeg_start_compress" >&6; } +if test "x$ac_cv_lib_jpeg_jpeg_start_compress" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBJPEG 1 +_ACEOF + + LIBS="-ljpeg $LIBS" + +else + as_fn_error $? "zm requires libjpeg.a" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5 +$as_echo_n "checking for pthread_create in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_pthread_create+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pthread_create (); +int +main () +{ +return pthread_create (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_pthread_pthread_create=yes +else + ac_cv_lib_pthread_pthread_create=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5 +$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; } +if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPTHREAD 1 +_ACEOF + + LIBS="-lpthread $LIBS" + +else + as_fn_error $? "zm requires libpthread.a" "$LINENO" 5 +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlsym in -ldl" >&5 +$as_echo_n "checking for dlsym in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlsym+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlsym (); +int +main () +{ +return dlsym (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_dl_dlsym=yes +else + ac_cv_lib_dl_dlsym=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlsym" >&5 +$as_echo "$ac_cv_lib_dl_dlsym" >&6; } +if test "x$ac_cv_lib_dl_dlsym" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBDL 1 +_ACEOF + + LIBS="-ldl $LIBS" + +else + as_fn_error $? "zm requires libdl.a" "$LINENO" 5 +fi + +if test "$ZM_SSL_LIB" == "openssl"; then +for ac_header in openssl/md5.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "openssl/md5.h" "ac_cv_header_openssl_md5_h" "$ac_includes_default" +if test "x$ac_cv_header_openssl_md5_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OPENSSL_MD5_H 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zm requires openssl/md5.h header to be installed for openssl" >&5 +$as_echo "$as_me: WARNING: zm requires openssl/md5.h header to be installed for openssl" >&2;} +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MD5 in -lcrypto" >&5 +$as_echo_n "checking for MD5 in -lcrypto... " >&6; } +if ${ac_cv_lib_crypto_MD5+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcrypto $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char MD5 (); +int +main () +{ +return MD5 (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_crypto_MD5=yes +else + ac_cv_lib_crypto_MD5=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_MD5" >&5 +$as_echo "$ac_cv_lib_crypto_MD5" >&6; } +if test "x$ac_cv_lib_crypto_MD5" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCRYPTO 1 +_ACEOF + + LIBS="-lcrypto $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libcrypto.a is required for authenticated streaming - use ZM_SSL_LIB option to select gnutls instead" >&5 +$as_echo "$as_me: WARNING: libcrypto.a is required for authenticated streaming - use ZM_SSL_LIB option to select gnutls instead" >&2;} +fi + +else +for ac_header in gnutls/openssl.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "gnutls/openssl.h" "ac_cv_header_gnutls_openssl_h" "$ac_includes_default" +if test "x$ac_cv_header_gnutls_openssl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GNUTLS_OPENSSL_H 1 +_ACEOF + ZM_HAS_GNUTLS_OPENSSL=1 + +else + ZM_HAS_GNUTLS_OPENSSL=0 + +fi + +done + +for ac_header in gnutls/gnutls.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "gnutls/gnutls.h" "ac_cv_header_gnutls_gnutls_h" "$ac_includes_default" +if test "x$ac_cv_header_gnutls_gnutls_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GNUTLS_GNUTLS_H 1 +_ACEOF + ZM_HAS_GNUTLS=1 + +else + ZM_HAS_GNUTLS=0 + +fi + +done + +if test "$ZM_HAS_GNUTLS_OPENSSL" == "0" && test "$ZM_HAS_GNUTLS" == "0"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gnutls is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&5 +$as_echo "$as_me: WARNING: gnutls is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&2;} +fi +for ac_header in gcrypt.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "gcrypt.h" "ac_cv_header_gcrypt_h" "$ac_includes_default" +if test "x$ac_cv_header_gcrypt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GCRYPT_H 1 +_ACEOF + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zm requires libgcrypt header to be installed for gnutls" >&5 +$as_echo "$as_me: WARNING: zm requires libgcrypt header to be installed for gnutls" >&2;} +fi + +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcry_check_version in -lgcrypt" >&5 +$as_echo_n "checking for gcry_check_version in -lgcrypt... " >&6; } +if ${ac_cv_lib_gcrypt_gcry_check_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgcrypt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gcry_check_version (); +int +main () +{ +return gcry_check_version (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_gcrypt_gcry_check_version=yes +else + ac_cv_lib_gcrypt_gcry_check_version=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gcrypt_gcry_check_version" >&5 +$as_echo "$ac_cv_lib_gcrypt_gcry_check_version" >&6; } +if test "x$ac_cv_lib_gcrypt_gcry_check_version" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGCRYPT 1 +_ACEOF + + LIBS="-lgcrypt $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libgcrypt.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&5 +$as_echo "$as_me: WARNING: libgcrypt.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for gnutls_fingerprint in -lgnutls" >&5 +$as_echo_n "checking for gnutls_fingerprint in -lgnutls... " >&6; } +if ${ac_cv_lib_gnutls_gnutls_fingerprint+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lgnutls $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gnutls_fingerprint (); +int +main () +{ +return gnutls_fingerprint (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_gnutls_gnutls_fingerprint=yes +else + ac_cv_lib_gnutls_gnutls_fingerprint=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gnutls_gnutls_fingerprint" >&5 +$as_echo "$ac_cv_lib_gnutls_gnutls_fingerprint" >&6; } +if test "x$ac_cv_lib_gnutls_gnutls_fingerprint" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBGNUTLS 1 +_ACEOF + + LIBS="-lgnutls $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libgnutls.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&5 +$as_echo "$as_me: WARNING: libgnutls.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead" >&2;} +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pcre_compile in -lpcre" >&5 +$as_echo_n "checking for pcre_compile in -lpcre... " >&6; } +if ${ac_cv_lib_pcre_pcre_compile+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpcre $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char pcre_compile (); +int +main () +{ +return pcre_compile (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_pcre_pcre_compile=yes +else + ac_cv_lib_pcre_pcre_compile=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pcre_pcre_compile" >&5 +$as_echo "$ac_cv_lib_pcre_pcre_compile" >&6; } +if test "x$ac_cv_lib_pcre_pcre_compile" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBPCRE 1 +_ACEOF + + LIBS="-lpcre $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libpcre.a may be required for remote/network camera support" >&5 +$as_echo "$as_me: WARNING: libpcre.a may be required for remote/network camera support" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlibVersion in -lz" >&5 +$as_echo_n "checking for zlibVersion in -lz... " >&6; } +if ${ac_cv_lib_z_zlibVersion+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char zlibVersion (); +int +main () +{ +return zlibVersion (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_z_zlibVersion=yes +else + ac_cv_lib_z_zlibVersion=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_zlibVersion" >&5 +$as_echo "$ac_cv_lib_z_zlibVersion" >&6; } +if test "x$ac_cv_lib_z_zlibVersion" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for x264_predict_16x16_init in -lx264" >&5 +$as_echo_n "checking for x264_predict_16x16_init in -lx264... " >&6; } +if ${ac_cv_lib_x264_x264_predict_16x16_init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lx264 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char x264_predict_16x16_init (); +int +main () +{ +return x264_predict_16x16_init (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_x264_x264_predict_16x16_init=yes +else + ac_cv_lib_x264_x264_predict_16x16_init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_x264_x264_predict_16x16_init" >&5 +$as_echo "$ac_cv_lib_x264_x264_predict_16x16_init" >&6; } +if test "x$ac_cv_lib_x264_x264_predict_16x16_init" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBX264 1 +_ACEOF + + LIBS="-lx264 $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for av_malloc in -lavutil" >&5 +$as_echo_n "checking for av_malloc in -lavutil... " >&6; } +if ${ac_cv_lib_avutil_av_malloc+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavutil $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char av_malloc (); +int +main () +{ +return av_malloc (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_avutil_av_malloc=yes +else + ac_cv_lib_avutil_av_malloc=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avutil_av_malloc" >&5 +$as_echo "$ac_cv_lib_avutil_av_malloc" >&6; } +if test "x$ac_cv_lib_avutil_av_malloc" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVUTIL 1 +_ACEOF + + LIBS="-lavutil $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libavutil.a may be required for MPEG streaming" >&5 +$as_echo "$as_me: WARNING: libavutil.a may be required for MPEG streaming" >&2;} +fi + +# Don't bother to warn about this one +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for av_image_copy in -lavcore" >&5 +$as_echo_n "checking for av_image_copy in -lavcore... " >&6; } +if ${ac_cv_lib_avcore_av_image_copy+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavcore $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char av_image_copy (); +int +main () +{ +return av_image_copy (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_avcore_av_image_copy=yes +else + ac_cv_lib_avcore_av_image_copy=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avcore_av_image_copy" >&5 +$as_echo "$ac_cv_lib_avcore_av_image_copy" >&6; } +if test "x$ac_cv_lib_avcore_av_image_copy" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVCORE 1 +_ACEOF + + LIBS="-lavcore $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for avcodec_open in -lavcodec" >&5 +$as_echo_n "checking for avcodec_open in -lavcodec... " >&6; } +if ${ac_cv_lib_avcodec_avcodec_open+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavcodec $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char avcodec_open (); +int +main () +{ +return avcodec_open (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_avcodec_avcodec_open=yes +else + ac_cv_lib_avcodec_avcodec_open=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avcodec_avcodec_open" >&5 +$as_echo "$ac_cv_lib_avcodec_avcodec_open" >&6; } +if test "x$ac_cv_lib_avcodec_avcodec_open" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVCODEC 1 +_ACEOF + + LIBS="-lavcodec $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libavcodec.a is required for MPEG streaming" >&5 +$as_echo "$as_me: WARNING: libavcodec.a is required for MPEG streaming" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for av_new_stream in -lavformat" >&5 +$as_echo_n "checking for av_new_stream in -lavformat... " >&6; } +if ${ac_cv_lib_avformat_av_new_stream+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavformat $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char av_new_stream (); +int +main () +{ +return av_new_stream (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_avformat_av_new_stream=yes +else + ac_cv_lib_avformat_av_new_stream=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avformat_av_new_stream" >&5 +$as_echo "$ac_cv_lib_avformat_av_new_stream" >&6; } +if test "x$ac_cv_lib_avformat_av_new_stream" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVFORMAT 1 +_ACEOF + + LIBS="-lavformat $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libavformat.a is required for MPEG streaming" >&5 +$as_echo "$as_me: WARNING: libavformat.a is required for MPEG streaming" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for avdevice_register_all in -lavdevice" >&5 +$as_echo_n "checking for avdevice_register_all in -lavdevice... " >&6; } +if ${ac_cv_lib_avdevice_avdevice_register_all+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lavdevice $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char avdevice_register_all (); +int +main () +{ +return avdevice_register_all (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_avdevice_avdevice_register_all=yes +else + ac_cv_lib_avdevice_avdevice_register_all=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_avdevice_avdevice_register_all" >&5 +$as_echo "$ac_cv_lib_avdevice_avdevice_register_all" >&6; } +if test "x$ac_cv_lib_avdevice_avdevice_register_all" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVDEVICE 1 +_ACEOF + + LIBS="-lavdevice $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libavdevice.a may be required for MPEG streaming" >&5 +$as_echo "$as_me: WARNING: libavdevice.a may be required for MPEG streaming" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sws_scale in -lswscale" >&5 +$as_echo_n "checking for sws_scale in -lswscale... " >&6; } +if ${ac_cv_lib_swscale_sws_scale+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lswscale -lswscale $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sws_scale (); +int +main () +{ +return sws_scale (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_swscale_sws_scale=yes +else + ac_cv_lib_swscale_sws_scale=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_swscale_sws_scale" >&5 +$as_echo "$ac_cv_lib_swscale_sws_scale" >&6; } +if test "x$ac_cv_lib_swscale_sws_scale" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSWSCALE 1 +_ACEOF + + LIBS="-lswscale $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BZ2_bzCompress in -lbz2" >&5 +$as_echo_n "checking for BZ2_bzCompress in -lbz2... " >&6; } +if ${ac_cv_lib_bz2_BZ2_bzCompress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lbz2 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char BZ2_bzCompress (); +int +main () +{ +return BZ2_bzCompress (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_bz2_BZ2_bzCompress=yes +else + ac_cv_lib_bz2_BZ2_bzCompress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bz2_BZ2_bzCompress" >&5 +$as_echo "$ac_cv_lib_bz2_BZ2_bzCompress" >&6; } +if test "x$ac_cv_lib_bz2_BZ2_bzCompress" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBBZ2 1 +_ACEOF + + LIBS="-lbz2 $LIBS" + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zm requires libbz2.a for recent versions of ffmpeg" >&5 +$as_echo "$as_me: WARNING: zm requires libbz2.a for recent versions of ffmpeg" >&2;} +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5 +$as_echo_n "checking for compress in -lz... " >&6; } +if ${ac_cv_lib_z_compress+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char compress (); +int +main () +{ +return compress (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_z_compress=yes +else + ac_cv_lib_z_compress=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5 +$as_echo "$ac_cv_lib_z_compress" >&6; } +if test "x$ac_cv_lib_z_compress" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + + +# Checks for header files. +# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works +# for constant arguments. Useless! +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5 +$as_echo_n "checking for working alloca.h... " >&6; } +if ${ac_cv_working_alloca_h+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +char *p = (char *) alloca (2 * sizeof (int)); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_working_alloca_h=yes +else + ac_cv_working_alloca_h=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5 +$as_echo "$ac_cv_working_alloca_h" >&6; } +if test $ac_cv_working_alloca_h = yes; then + +$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5 +$as_echo_n "checking for alloca... " >&6; } +if ${ac_cv_func_alloca_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __GNUC__ +# define alloca __builtin_alloca +#else +# ifdef _MSC_VER +# include +# define alloca _alloca +# else +# ifdef HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + #pragma alloca +# else +# ifndef alloca /* predefined by HP cc +Olibcalls */ +void *alloca (size_t); +# endif +# endif +# endif +# endif +#endif + +int +main () +{ +char *p = (char *) alloca (1); + if (p) return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_func_alloca_works=yes +else + ac_cv_func_alloca_works=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5 +$as_echo "$ac_cv_func_alloca_works" >&6; } + +if test $ac_cv_func_alloca_works = yes; then + +$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h + +else + # The SVR3 libPW and SVR4 libucb both contain incompatible functions +# that cause trouble. Some versions do not even contain alloca or +# contain a buggy version. If you still want to use their alloca, +# use ar to extract alloca.o from them instead of compiling alloca.c. + +ALLOCA=\${LIBOBJDIR}alloca.$ac_objext + +$as_echo "#define C_ALLOCA 1" >>confdefs.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5 +$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; } +if ${ac_cv_os_cray+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#if defined CRAY && ! defined CRAY2 +webecray +#else +wenotbecray +#endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "webecray" >/dev/null 2>&1; then : + ac_cv_os_cray=yes +else + ac_cv_os_cray=no +fi +rm -f conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5 +$as_echo "$ac_cv_os_cray" >&6; } +if test $ac_cv_os_cray = yes; then + for ac_func in _getb67 GETB67 getb67; do + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_cxx_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + +cat >>confdefs.h <<_ACEOF +#define CRAY_STACKSEG_END $ac_func +_ACEOF + + break +fi + + done +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5 +$as_echo_n "checking stack direction for C alloca... " >&6; } +if ${ac_cv_c_stack_direction+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_c_stack_direction=0 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$ac_includes_default +int +find_stack_direction (int *addr, int depth) +{ + int dir, dummy = 0; + if (! addr) + addr = &dummy; + *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1; + dir = depth ? find_stack_direction (addr, depth - 1) : 0; + return dir + dummy; +} + +int +main (int argc, char **argv) +{ + return find_stack_direction (0, argc + !argv + 20) < 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + ac_cv_c_stack_direction=1 +else + ac_cv_c_stack_direction=-1 +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5 +$as_echo "$ac_cv_c_stack_direction" >&6; } +cat >>confdefs.h <<_ACEOF +#define STACK_DIRECTION $ac_cv_c_stack_direction +_ACEOF + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +for ac_header in fcntl.h limits.h memory.h stddef.h stdlib.h string.h strings.h sys/param.h sys/time.h syslog.h unistd.h values.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/socket.h sys/un.h glob.h sys/sendfile.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +for ac_header in execinfo.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default" +if test "x$ac_cv_header_execinfo_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_EXECINFO_H 1 +_ACEOF + +fi + +done + +for ac_header in syscall.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "syscall.h" "ac_cv_header_syscall_h" "$ac_includes_default" +if test "x$ac_cv_header_syscall_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYSCALL_H 1 +_ACEOF + +fi + +done + +for ac_header in pthread.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PTHREAD_H 1 +_ACEOF + +fi + +done + +for ac_header in linux/videodev.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "linux/videodev.h" "ac_cv_header_linux_videodev_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_videodev_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_VIDEODEV_H 1 +_ACEOF + ZM_HAS_V4L1=1 + +else + ZM_HAS_V4L1=0 + +fi + +done + +for ac_header in linux/videodev2.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "linux/videodev2.h" "ac_cv_header_linux_videodev2_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_videodev2_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LINUX_VIDEODEV2_H 1 +_ACEOF + ZM_HAS_V4L2=1 + +else + ZM_HAS_V4L2=0 + +fi + +done + +if test "$ZM_HAS_V4L1" == "1" || test "$ZM_HAS_V4L2" == "1"; then +ZM_HAS_V4L=1 + +else +ZM_HAS_V4L=0 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: zm requires Video4Linux or Video4Linux2 to be installed for analog or USB camera support" >&5 +$as_echo "$as_me: WARNING: zm requires Video4Linux or Video4Linux2 to be installed for analog or USB camera support" >&2;} +fi +for ac_header in jpeglib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "jpeglib.h" "ac_cv_header_jpeglib_h" "$ac_includes_default" +if test "x$ac_cv_header_jpeglib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_JPEGLIB_H 1 +_ACEOF + +else + as_fn_error $? "zm requires libjpeg headers to be installed" "$LINENO" 5 +fi + +done + +for ac_header in mysql/mysql.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "mysql/mysql.h" "ac_cv_header_mysql_mysql_h" "$ac_includes_default" +if test "x$ac_cv_header_mysql_mysql_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MYSQL_MYSQL_H 1 +_ACEOF + +else + as_fn_error $? "zm requires MySQL headers - check that MySQL development packages are installed" "$LINENO" 5 +fi + +done + +for ac_header in libavutil/avutil.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libavutil/avutil.h" "ac_cv_header_libavutil_avutil_h" "$ac_includes_default" +if test "x$ac_cv_header_libavutil_avutil_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVUTIL_AVUTIL_H 1 +_ACEOF + +fi + +done + +for ac_header in libavcodec/avcodec.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libavcodec/avcodec.h" "ac_cv_header_libavcodec_avcodec_h" "$ac_includes_default" +if test "x$ac_cv_header_libavcodec_avcodec_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVCODEC_AVCODEC_H 1 +_ACEOF + +fi + +done + +for ac_header in libavformat/avformat.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libavformat/avformat.h" "ac_cv_header_libavformat_avformat_h" "$ac_includes_default" +if test "x$ac_cv_header_libavformat_avformat_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBAVFORMAT_AVFORMAT_H 1 +_ACEOF + +fi + +done + +for ac_header in libswscale/swscale.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "libswscale/swscale.h" "ac_cv_header_libswscale_swscale_h" "$ac_includes_default" +if test "x$ac_cv_header_libswscale_swscale_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSWSCALE_SWSCALE_H 1 +_ACEOF + +fi + +done + +for ac_header in pcre/pcre.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "pcre/pcre.h" "ac_cv_header_pcre_pcre_h" "$ac_includes_default" +if test "x$ac_cv_header_pcre_pcre_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PCRE_PCRE_H 1 +_ACEOF + ZM_PCRE="1" + +fi + +done + +for ac_header in pcre.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "pcre.h" "ac_cv_header_pcre_h" "$ac_includes_default" +if test "x$ac_cv_header_pcre_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PCRE_H 1 +_ACEOF + ZM_PCRE="1" + +fi + +done + +if test "$ENABLE_MMAP" == "yes"; then +for ac_header in sys/mman.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_mman_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_MMAN_H 1 +_ACEOF + +fi + +done + +for ac_header in fcntl.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "fcntl.h" "ac_cv_header_fcntl_h" "$ac_includes_default" +if test "x$ac_cv_header_fcntl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FCNTL_H 1 +_ACEOF + +fi + +done + +else +for ac_header in sys/ipc.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/ipc.h" "ac_cv_header_sys_ipc_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_ipc_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_IPC_H 1 +_ACEOF + +fi + +done + +for ac_header in sys/shm.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "sys/shm.h" "ac_cv_header_sys_shm_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_shm_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SHM_H 1 +_ACEOF + +fi + +done + +fi +for ac_header in zlib.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + +fi + +done + + +ac_fn_cxx_check_decl "$LINENO" "round" "ac_cv_have_decl_round" "#include +" +if test "x$ac_cv_have_decl_round" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_ROUND $ac_have_decl +_ACEOF + +if test "$ZM_SSL_LIB" == "openssl"; then +ac_fn_cxx_check_decl "$LINENO" "MD5" "ac_cv_have_decl_MD5" "#include +#include +" +if test "x$ac_cv_have_decl_MD5" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MD5 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "zm requires openssl/md5.h - use ZM_SSL_LIB option to select gnutls instead" "$LINENO" 5 +fi + +else +if test "$ZM_HAS_GNUTLS_OPENSSL" == "1"; then +ac_fn_cxx_check_decl "$LINENO" "MD5" "ac_cv_have_decl_MD5" "#include +#include +" +if test "x$ac_cv_have_decl_MD5" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_MD5 $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "zm requires gnutls/openssl.h - use ZM_SSL_LIB option to select openssl instead" "$LINENO" 5 +fi + +else +ac_fn_cxx_check_decl "$LINENO" "gnutls_fingerprint" "ac_cv_have_decl_gnutls_fingerprint" "#include +#include +" +if test "x$ac_cv_have_decl_gnutls_fingerprint" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_GNUTLS_FINGERPRINT $ac_have_decl +_ACEOF +if test $ac_have_decl = 1; then : + +else + as_fn_error $? "zm requires gnutls/gnutls.h - use ZM_SSL_LIB option to select openssl instead" "$LINENO" 5 +fi + +fi +fi +ac_fn_cxx_check_decl "$LINENO" "backtrace" "ac_cv_have_decl_backtrace" "#include +" +if test "x$ac_cv_have_decl_backtrace" = xyes; then : + ac_have_decl=1 +else + ac_have_decl=0 +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_DECL_BACKTRACE $ac_have_decl +_ACEOF + + + + +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +# Check if version of Perl is sufficient +ac_perl_version="5.6.0" + +if test "x$PERL" != "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl version greater than or equal to $ac_perl_version" >&5 +$as_echo_n "checking for perl version greater than or equal to $ac_perl_version... " >&6; } + # NB: It would be nice to log the error if there is one, but we cannot rely + # on autoconf internals + $PERL -e "use $ac_perl_version;" > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi + + +# Compulsory perl modules +ac_perl_modules="Sys::Syslog" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires SYS:Syslog" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="DBI" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires DBI" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="DBD::mysql" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires DBD::mysql" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Getopt::Long" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires Getopt::Long" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Time::HiRes" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires Time::HiRes" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Date::Manip" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires Date::Manip" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="LWP::UserAgent" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires LWP::UserAgent" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="ExtUtils::MakeMaker" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires ExtUtils::MakeMaker" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +if test "$ENABLE_MMAP" == "yes"; then +ac_perl_modules="Sys::Mmap" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + as_fn_error $? "zm requires Sys::Mmap for mapped memory - set --enable-mmap=no to use IPC shared memory instead" "$LINENO" 5 + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +fi + +# Optional perl modules +ac_perl_modules="Module::Load" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Module::Load is required for PTZ camera control" >&5 +$as_echo "$as_me: WARNING: Module::Load is required for PTZ camera control" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Device::SerialPort" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Device::SerialPort is required for RS232/RS485 PTZ camera control" >&5 +$as_echo "$as_me: WARNING: Device::SerialPort is required for RS232/RS485 PTZ camera control" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Net::FTP" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Net::FTP is required for automatic event uploading using ftp" >&5 +$as_echo "$as_me: WARNING: Net::FTP is required for automatic event uploading using ftp" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Net::SFTP::Foreign" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Net::SFTP::Foreign is required for automatic event uploading using sftp" >&5 +$as_echo "$as_me: WARNING: Net::SFTP::Foreign is required for automatic event uploading using sftp" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Expect" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Expect is required for automatic event uploading using sftp" >&5 +$as_echo "$as_me: WARNING: Expect is required for automatic event uploading using sftp" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Archive::Tar" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Archive::Tar may be required for automatic event uploading" >&5 +$as_echo "$as_me: WARNING: Archive::Tar may be required for automatic event uploading" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Archive::Zip" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Archive::Zip may be required for automatic event uploading" >&5 +$as_echo "$as_me: WARNING: Archive::Zip may be required for automatic event uploading" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="Net::SMTP" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Net::SMTP may be required for automatic event email notification" >&5 +$as_echo "$as_me: WARNING: Net::SMTP may be required for automatic event email notification" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="MIME::Lite" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MIME::Lite may be required for automatic event email notification" >&5 +$as_echo "$as_me: WARNING: MIME::Lite may be required for automatic event email notification" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="MIME::Entity" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: MIME::Entity may be required for automatic event email notification" >&5 +$as_echo "$as_me: WARNING: MIME::Entity may be required for automatic event email notification" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi +ac_perl_modules="X10::ActiveHome" +# Make sure we have perl +if test -z "$PERL"; then +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test "x$PERL" != x; then + ac_perl_modules_failed=0 + for ac_perl_module in $ac_perl_modules; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for perl module $ac_perl_module" >&5 +$as_echo_n "checking for perl module $ac_perl_module... " >&6; } + + # Would be nice to log result here, but can't rely on autoconf internals + $PERL "-M$ac_perl_module" -e exit > /dev/null 2>&1 + if test $? -ne 0; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; + ac_perl_modules_failed=1 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; }; + fi + done + + # Run optional shell commands + if test "$ac_perl_modules_failed" = 0; then + : + + else + : + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: X10::ActiveHome is required for X.10 support" >&5 +$as_echo "$as_me: WARNING: X10::ActiveHome is required for X.10 support" >&2;} + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find perl" >&5 +$as_echo "$as_me: WARNING: could not find perl" >&2;} +fi + + + prefix_NONE= + exec_prefix_NONE= + test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix + eval ac_define_dir="\"$bindir\"" + eval ac_define_dir="\"$ac_define_dir\"" + BINDIR="$ac_define_dir" + + +cat >>confdefs.h <<_ACEOF +#define BINDIR "$ac_define_dir" +_ACEOF + + test "$prefix_NONE" && prefix=NONE + test "$exec_prefix_NONE" && exec_prefix=NONE + + + prefix_NONE= + exec_prefix_NONE= + test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix + eval ac_define_dir="\"$libdir\"" + eval ac_define_dir="\"$ac_define_dir\"" + LIBDIR="$ac_define_dir" + + +cat >>confdefs.h <<_ACEOF +#define LIBDIR "$ac_define_dir" +_ACEOF + + test "$prefix_NONE" && prefix=NONE + test "$exec_prefix_NONE" && exec_prefix=NONE + +ZM_PID="$ZM_RUNDIR/zm.pid" + + + prefix_NONE= + exec_prefix_NONE= + test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix + test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix + eval ac_define_dir="\"$sysconfdir\"" + eval ac_define_dir="\"$ac_define_dir\"" + SYSCONFDIR="$ac_define_dir" + + +cat >>confdefs.h <<_ACEOF +#define SYSCONFDIR "$ac_define_dir" +_ACEOF + + test "$prefix_NONE" && prefix=NONE + test "$exec_prefix_NONE" && exec_prefix=NONE + +ZM_CONFIG="$SYSCONFDIR/zm.conf" + + +# Slight hack for non-standard perl install paths +if test "$prefix" != "NONE"; then + PERL_SITE_PREFIX=`perl -V:siteprefix | sed -e "s/.*='\(.*\)';/\1/"` + PERL_SITE_LIB=`perl -V:installsitelib | sed -e "s/.*='\(.*\)';/\1/"` + PERL_LIB_PATH=`echo $PERL_SITE_LIB | sed -e "s|^$PERL_SITE_PREFIX||"` + EXTRA_PERL_LIB="use lib '$prefix$PERL_LIB_PATH'; # Include custom perl install path" + PERL_MM_PARMS="PREFIX=$prefix" +else + EXTRA_PERL_LIB="# Include from system perl paths only" + PERL_MM_PARMS= +fi + + + +ac_config_files="$ac_config_files Makefile zm.conf zmconfgen.pl db/Makefile db/zm_create.sql misc/Makefile misc/apache.conf misc/logrotate.conf misc/syslog.conf scripts/Makefile scripts/zm scripts/zmaudit.pl scripts/zmcontrol.pl scripts/zmdc.pl scripts/zmfilter.pl scripts/zmpkg.pl scripts/zmtrack.pl scripts/zmtrigger.pl scripts/zmupdate.pl scripts/zmvideo.pl scripts/zmwatch.pl scripts/zmx10.pl scripts/zmdbbackup scripts/zmdbrestore scripts/zmeventdump scripts/zmlogrotate.conf scripts/ZoneMinder/lib/ZoneMinder/Base.pm scripts/ZoneMinder/lib/ZoneMinder/Config.pm scripts/ZoneMinder/lib/ZoneMinder/Memory.pm scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm src/Makefile src/zm_config.h web/Makefile web/ajax/Makefile web/css/Makefile web/graphics/Makefile web/includes/Makefile web/includes/config.php web/js/Makefile web/lang/Makefile web/skins/Makefile web/skins/classic/Makefile web/skins/classic/ajax/Makefile web/skins/classic/css/Makefile web/skins/classic/graphics/Makefile web/skins/classic/includes/Makefile web/skins/classic/js/Makefile web/skins/classic/lang/Makefile web/skins/classic/views/Makefile web/skins/classic/views/css/Makefile web/skins/classic/views/js/Makefile web/skins/mobile/Makefile web/skins/mobile/ajax/Makefile web/skins/mobile/css/Makefile web/skins/mobile/graphics/Makefile web/skins/mobile/includes/Makefile web/skins/mobile/lang/Makefile web/skins/mobile/views/Makefile web/skins/mobile/views/css/Makefile web/tools/Makefile web/tools/mootools/Makefile web/views/Makefile web/skins/xml/Makefile web/skins/xml/views/Makefile web/skins/xml/includes/Makefile" + + +# Create the definitions for compilation and defaults for the database +ac_config_commands="$ac_config_commands src/zm_config_defines.h" + +# Manually generate the perl Makefile maker +ac_config_commands="$ac_config_commands scripts/ZoneMinder/Makefile" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + if test -n "$EXEEXT"; then + am__EXEEXT_TRUE= + am__EXEEXT_FALSE='#' +else + am__EXEEXT_TRUE='#' + am__EXEEXT_FALSE= +fi + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + as_fn_error $? "conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCXX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by zm $as_me 1.25.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to . +zm home page: ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +zm config.status 1.25.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +MKDIR_P='$MKDIR_P' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +PERL_MM_PARMS=$PERL_MM_PARMS + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "zm.conf") CONFIG_FILES="$CONFIG_FILES zm.conf" ;; + "zmconfgen.pl") CONFIG_FILES="$CONFIG_FILES zmconfgen.pl" ;; + "db/Makefile") CONFIG_FILES="$CONFIG_FILES db/Makefile" ;; + "db/zm_create.sql") CONFIG_FILES="$CONFIG_FILES db/zm_create.sql" ;; + "misc/Makefile") CONFIG_FILES="$CONFIG_FILES misc/Makefile" ;; + "misc/apache.conf") CONFIG_FILES="$CONFIG_FILES misc/apache.conf" ;; + "misc/logrotate.conf") CONFIG_FILES="$CONFIG_FILES misc/logrotate.conf" ;; + "misc/syslog.conf") CONFIG_FILES="$CONFIG_FILES misc/syslog.conf" ;; + "scripts/Makefile") CONFIG_FILES="$CONFIG_FILES scripts/Makefile" ;; + "scripts/zm") CONFIG_FILES="$CONFIG_FILES scripts/zm" ;; + "scripts/zmaudit.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmaudit.pl" ;; + "scripts/zmcontrol.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmcontrol.pl" ;; + "scripts/zmdc.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmdc.pl" ;; + "scripts/zmfilter.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmfilter.pl" ;; + "scripts/zmpkg.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmpkg.pl" ;; + "scripts/zmtrack.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmtrack.pl" ;; + "scripts/zmtrigger.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmtrigger.pl" ;; + "scripts/zmupdate.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmupdate.pl" ;; + "scripts/zmvideo.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmvideo.pl" ;; + "scripts/zmwatch.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmwatch.pl" ;; + "scripts/zmx10.pl") CONFIG_FILES="$CONFIG_FILES scripts/zmx10.pl" ;; + "scripts/zmdbbackup") CONFIG_FILES="$CONFIG_FILES scripts/zmdbbackup" ;; + "scripts/zmdbrestore") CONFIG_FILES="$CONFIG_FILES scripts/zmdbrestore" ;; + "scripts/zmeventdump") CONFIG_FILES="$CONFIG_FILES scripts/zmeventdump" ;; + "scripts/zmlogrotate.conf") CONFIG_FILES="$CONFIG_FILES scripts/zmlogrotate.conf" ;; + "scripts/ZoneMinder/lib/ZoneMinder/Base.pm") CONFIG_FILES="$CONFIG_FILES scripts/ZoneMinder/lib/ZoneMinder/Base.pm" ;; + "scripts/ZoneMinder/lib/ZoneMinder/Config.pm") CONFIG_FILES="$CONFIG_FILES scripts/ZoneMinder/lib/ZoneMinder/Config.pm" ;; + "scripts/ZoneMinder/lib/ZoneMinder/Memory.pm") CONFIG_FILES="$CONFIG_FILES scripts/ZoneMinder/lib/ZoneMinder/Memory.pm" ;; + "scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm") CONFIG_FILES="$CONFIG_FILES scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "src/zm_config.h") CONFIG_FILES="$CONFIG_FILES src/zm_config.h" ;; + "web/Makefile") CONFIG_FILES="$CONFIG_FILES web/Makefile" ;; + "web/ajax/Makefile") CONFIG_FILES="$CONFIG_FILES web/ajax/Makefile" ;; + "web/css/Makefile") CONFIG_FILES="$CONFIG_FILES web/css/Makefile" ;; + "web/graphics/Makefile") CONFIG_FILES="$CONFIG_FILES web/graphics/Makefile" ;; + "web/includes/Makefile") CONFIG_FILES="$CONFIG_FILES web/includes/Makefile" ;; + "web/includes/config.php") CONFIG_FILES="$CONFIG_FILES web/includes/config.php" ;; + "web/js/Makefile") CONFIG_FILES="$CONFIG_FILES web/js/Makefile" ;; + "web/lang/Makefile") CONFIG_FILES="$CONFIG_FILES web/lang/Makefile" ;; + "web/skins/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/Makefile" ;; + "web/skins/classic/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/Makefile" ;; + "web/skins/classic/ajax/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/ajax/Makefile" ;; + "web/skins/classic/css/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/css/Makefile" ;; + "web/skins/classic/graphics/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/graphics/Makefile" ;; + "web/skins/classic/includes/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/includes/Makefile" ;; + "web/skins/classic/js/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/js/Makefile" ;; + "web/skins/classic/lang/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/lang/Makefile" ;; + "web/skins/classic/views/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/views/Makefile" ;; + "web/skins/classic/views/css/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/views/css/Makefile" ;; + "web/skins/classic/views/js/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/classic/views/js/Makefile" ;; + "web/skins/mobile/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/Makefile" ;; + "web/skins/mobile/ajax/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/ajax/Makefile" ;; + "web/skins/mobile/css/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/css/Makefile" ;; + "web/skins/mobile/graphics/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/graphics/Makefile" ;; + "web/skins/mobile/includes/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/includes/Makefile" ;; + "web/skins/mobile/lang/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/lang/Makefile" ;; + "web/skins/mobile/views/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/views/Makefile" ;; + "web/skins/mobile/views/css/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/mobile/views/css/Makefile" ;; + "web/tools/Makefile") CONFIG_FILES="$CONFIG_FILES web/tools/Makefile" ;; + "web/tools/mootools/Makefile") CONFIG_FILES="$CONFIG_FILES web/tools/mootools/Makefile" ;; + "web/views/Makefile") CONFIG_FILES="$CONFIG_FILES web/views/Makefile" ;; + "web/skins/xml/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/xml/Makefile" ;; + "web/skins/xml/views/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/xml/views/Makefile" ;; + "web/skins/xml/includes/Makefile") CONFIG_FILES="$CONFIG_FILES web/skins/xml/includes/Makefile" ;; + "src/zm_config_defines.h") CONFIG_COMMANDS="$CONFIG_COMMANDS src/zm_config_defines.h" ;; + "scripts/ZoneMinder/Makefile") CONFIG_COMMANDS="$CONFIG_COMMANDS scripts/ZoneMinder/Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac + ac_MKDIR_P=$MKDIR_P + case $MKDIR_P in + [\\/$]* | ?:[\\/]* ) ;; + */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +s&@MKDIR_P@&$ac_MKDIR_P&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi +# Compute "$ac_file"'s index in $config_headers. +_am_arg="$ac_file" +_am_stamp_count=1 +for _am_header in $config_headers :; do + case $_am_header in + $_am_arg | $_am_arg:* ) + break ;; + * ) + _am_stamp_count=`expr $_am_stamp_count + 1` ;; + esac +done +echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || +$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$_am_arg" : 'X\(//\)[^/]' \| \ + X"$_am_arg" : 'X\(//\)$' \| \ + X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$_am_arg" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'`/stamp-h$_am_stamp_count + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "depfiles":C) test x"$AMDEP_TRUE" != x"" || { + # Autoconf 2.62 quotes --file arguments for eval, but not when files + # are listed without --file. Let's play safe and only enable the eval + # if we detect the quoting. + case $CONFIG_FILES in + *\'*) eval set x "$CONFIG_FILES" ;; + *) set x $CONFIG_FILES ;; + esac + shift + for mf + do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # Grep'ing the whole file is not good either: AIX grep has a line + # limit of 2048, but all sed's we know have understand at least 4000. + if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then + dirpart=`$as_dirname -- "$mf" || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + else + continue + fi + # Extract the definition of DEPDIR, am__include, and am__quote + # from the Makefile without running `make'. + DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` + test -z "$DEPDIR" && continue + am__include=`sed -n 's/^am__include = //p' < "$mf"` + test -z "am__include" && continue + am__quote=`sed -n 's/^am__quote = //p' < "$mf"` + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n 's/^U = //p' < "$mf"` + # Find all dependency output files, they are included files with + # $(DEPDIR) in their names. We invoke sed twice because it is the + # simplest approach to changing $(DEPDIR) to its actual value in the + # expansion. + for file in `sed -n " + s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`$as_dirname -- "$file" || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir=$dirpart/$fdir; as_fn_mkdir_p + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done + done +} + ;; + "src/zm_config_defines.h":C) perl ./zmconfgen.pl ;; + "scripts/ZoneMinder/Makefile":C) (cd scripts/ZoneMinder; echo "perl Makefile.PL $PERL_MM_PARMS"; perl Makefile.PL $PERL_MM_PARMS) ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..6eeb952d7 --- /dev/null +++ b/configure.ac @@ -0,0 +1,399 @@ +AC_PREREQ(2.59) +AC_INIT(zm,1.25.0,[http://www.zoneminder.com/forums/ - Please check FAQ first],ZoneMinder,http://www.zoneminder.com/downloads.html) +AM_INIT_AUTOMAKE +AC_CONFIG_SRCDIR(src/zm.h) +AM_CONFIG_HEADER(config.h) + +PATH_BUILD=`pwd` +AC_SUBST(PATH_BUILD) +TIME_BUILD=`date +'%s'` +AC_SUBST(TIME_BUILD) + +AC_ARG_VAR(ZM_DB_HOST,[Hostname where ZoneMinder database located, default localhost]) +AC_ARG_VAR(ZM_DB_NAME,[Name of ZoneMinder database, default zm]) +AC_ARG_VAR(ZM_DB_USER,[Name of ZoneMinder database user, default zmuser]) +AC_ARG_VAR(ZM_DB_PASS,[Password of ZoneMinder database user, default zmpass]) +AC_ARG_VAR(ZM_SSL_LIB,[Library to use for ssl functions, default gnutls]) +AC_ARG_VAR(ZM_MYSQL_ENGINE,[MySQL engine to use with database, default MyISAM]) +AC_ARG_VAR(ZM_RUNDIR,[Location of transient process files, default /var/run/zm]) +AC_ARG_VAR(ZM_TMPDIR,[Location of temporary files, default /tmp/zm]) +AC_ARG_VAR(ZM_LOGDIR,[Location of generated log files, default /var/log/zm]) + +if test "$ZM_DB_HOST" == ""; then + AC_SUBST(ZM_DB_HOST,[localhost]) +fi +if test "$ZM_DB_NAME" == ""; then + AC_SUBST(ZM_DB_NAME,[zm]) +fi +if test "$ZM_DB_USER" == ""; then + AC_SUBST(ZM_DB_USER,[zmuser]) +fi +if test "$ZM_DB_PASS" == ""; then + AC_SUBST(ZM_DB_PASS,[zmpass]) +fi +if test "$ZM_SSL_LIB" == ""; then + AC_SUBST(ZM_SSL_LIB,gnutls) +fi +if test "$ZM_MYSQL_ENGINE" == ""; then + AC_SUBST(ZM_MYSQL_ENGINE,MyISAM) +fi +if test "$ZM_RUNDIR" == ""; then + AC_SUBST(ZM_RUNDIR,[/var/run/zm]) +fi +if test "$ZM_TMPDIR" == ""; then + AC_SUBST(ZM_TMPDIR,[/tmp/zm]) +fi +if test "$ZM_LOGDIR" == ""; then + AC_SUBST(ZM_LOGDIR,[/var/log/zm]) +fi + +LIB_ARCH=lib +AC_ARG_WITH(libarch, + [ --with-libarch= architecture library path to use, default lib], + [LIB_ARCH=$with_libarch], + AC_MSG_WARN([You can call configure with the --with-libarch option. + This tells configure where to find architecture specific libraries. + The default of 'lib' is usually ok but 64 bit machines may require lib64. + e.g. --with-libarch=lib or --with-libarch=lib64]) +) +AC_SUBST(LIB_ARCH) + +MYSQL_PREFIX=/usr +AC_ARG_WITH(mysql, + [ --with-mysql= prefix of MySQL installation, default /usr], + [MYSQL_PREFIX=$with_mysql], + AC_MSG_WARN([You can call configure with the --with-mysql option. + This tells configure where to find the MySql C library and headers if configure cannot + locate them automatically. + e.g. --with-mysql=/usr/local or --with-mysql=/usr]) +) +AC_SUBST(MYSQL_PREFIX) +MYSQL_LIBS="-L${MYSQL_PREFIX}/${LIB_ARCH}/mysql" +MYSQL_CFLAGS="-I${MYSQL_PREFIX}/include" +AC_SUBST(MYSQL_LIBS) +AC_SUBST(MYSQL_CFLAGS) + +LDFLAGS="${MYSQL_LIBS} $LDFLAGS" + +FFMPEG_PREFIX=/usr +AC_ARG_WITH(ffmpeg, + [ --with-ffmpeg= prefix of ffmpeg root directory for libavcodec etc, default /usr], + [FFMPEG_PREFIX=$with_ffmpeg], + AC_MSG_WARN([You can call configure with the --with-ffmpeg option. + This tells configure where to find the ffmpeg root directory within which are the libavcodec + and libavformat files that can be used to build true MPEG streaming into ZoneMinder. Ensure that + your copy of ffmpeg has installed libraries as well as binaries (use 'make installlib'). If you + are using a local install of ffmpeg you may have to remove or rename a previous real installation + as the headers and libraries from that will probably be picked up before your local copy. + e.g. --with-ffmpeg=/usr/local]) +) +AC_SUBST(FFMPEG_PREFIX) +FFMPEG_LIBS="-L${FFMPEG_PREFIX}/${LIB_ARCH}" +FFMPEG_CFLAGS="-I${FFMPEG_PREFIX}/include -D__STDC_CONSTANT_MACROS" +AC_SUBST(FFMPEG_LIBS) +AC_SUBST(FFMPEG_CFLAGS) + +LDFLAGS="${FFMPEG_LIBS} $LDFLAGS" +CFLAGS="${FFMPEG_CFLAGS} $CFLAGS" +CPPFLAGS="${FFMPEG_CFLAGS} $CPPFLAGS" + +EXTRA_LIBS= +AC_ARG_WITH(extralibs, + [ --with-extralibs="" string containing extra libraries to pass to link, default empty], + [EXTRA_LIBS=$with_extralibs], + AC_MSG_WARN([You can call configure with the --with-extralibs option. + Ordinarily you will need to use this option only when your copy of ffmpeg has been built + with support for additional formats and you would use this option to detail which additional + libraries ffmpeg was built with so that it is able to link successfully with ZoneMinder. + You will need to wrap this option in quotes if it contains any spaces. + e.g. --with-extralibs="-lmp3lame"]) +) +AC_SUBST(EXTRA_LIBS) + +LDFLAGS="$LDFLAGS ${EXTRA_LIBS}" + +AC_ARG_WITH(webdir, + [ --with-webdir= prefix of web directory], + [WEB_PREFIX=$with_webdir], + AC_MSG_ERROR([You must call configure with the --with-webdir option. + This tells configure where to install PHP and web files and scripts. + e.g. --with-webdir=/var/www/html or --with-webdir=/www/vhtdocs/]) +) +AC_SUBST(WEB_PREFIX) + +AC_ARG_WITH(cgidir, + [ --with-cgidir= prefix of cgi directory], + [CGI_PREFIX=$with_cgidir], + AC_MSG_ERROR([You must call configure with the --with-cgidir option. + This tells configure where to install cgi files and scripts. + e.g. --with-cgidir=/var/www/cgi-bin or --with-webdir=/www/vhtdocs//cgi-bin]) +) +AC_SUBST(CGI_PREFIX) + +WEB_USER=apache +AC_ARG_WITH(webuser, + [ --with-webuser= name of web user, default apache], + [WEB_USER=$with_webuser], + AC_MSG_WARN([You can call configure with the --with-webuser option. + This tells configure what the user name of the web user is if it is not the default of 'apache'. + e.g. --with-webuser=apache or --with-webuser=web]) +) +AC_SUBST(WEB_USER) + +WEB_GROUP=apache +AC_ARG_WITH(webgroup, + [ --with-webgroup= name of web group, default apache], + [WEB_GROUP=$with_webgroup], + AC_MSG_WARN([You can call configure with the --with-webgroup option. + This tells configure what the group name of the web group is if it is not the default of 'apache'. + e.g. --with-webgroup=apache or --with-webgroup=web]) +) +AC_SUBST(WEB_GROUP) + +WEB_HOST=zm.local +AC_ARG_WITH(webhost, + [ --with-webhost= name of web hostname, default zm.local], + [WEB_HOST=$with_webhost], + AC_MSG_WARN([You can call configure with the --with-webhost option. + This tells configure what the host name is for name based virtual hosting. This is only used to populate the sample web/zmHttpd.conf file. + e.g. --with-webhost=zm.localdomain]) +) +AC_SUBST(WEB_HOST) + +ENABLE_DEBUG=yes +AC_ARG_ENABLE(debug, + [ --enable-debug= enable or disable debug, default enabled], + [ENABLE_DEBUG=$enable_debug], + AC_MSG_WARN([You can call configure with the --enable-debug= or --disable-debug option. + This tells configure whether to compile ZoneMinder with debug included. Although debug is included + by default it is not output unless explicitly switched on elsewhere. These checks may induce a + small penalty on performance and if you are after squeezing the maximum possible performance out + of ZoneMinder you may use this switch to prevent debug from being compiled in. + e.g. --enable-debug=yes or --disable-debug]) +) +if test "$ENABLE_DEBUG" != "yes"; then + AC_DEFINE(ZM_DBG_OFF,1,"Whether debug is switched off and compiled out") +fi + +ENABLE_CRASHTRACE=yes +AC_ARG_ENABLE(crashtrace, + [ --enable-crashtrace= enable or disabled crash tracing, default enabled], + [ENABLE_CRASHTRACE=$enable_crashtrace], + AC_MSG_WARN([You can call configure with the --enable-crashtrace= or --disable-crashtrace option. + This tells configure whether to compile ZoneMinder with crash tracing included. This allows a + dump of the stack trace when a ZoneMinder binary crashes or is killed by an unexpected signal. + Although this should work on most systems it does rely on un(or loosely) documented features and + so should be regarded as experimental. If you experience problems compiling zm_signal.cpp or + ZoneMinder binaries fail to shut down correctly then you should probably disable this feature. + e.g. --enable-crashtrace=yes or --disable-crashtrace]) +) +if test "$ENABLE_CRASHTRACE" != "yes"; then + AC_DEFINE(ZM_NO_CRASHTRACE,1,"Whether crash tracing is switched off and compiled out") +fi + +ENABLE_MMAP=yes +AC_ARG_ENABLE(mmap, + [ --enable-mmap= enable or disabled mapped memory versus shared memory, default mapped], + [ENABLE_MMAP=$enable_mmap], + AC_MSG_WARN([You can call configure with the --enable-mmap= or --disable-mmap option. + This tells configure whether to compile ZoneMinder with mmap support rather than IPC shared + memory. This is a feature that uses memory mapped into files which all processes can share. + Memory mapping requires less configuration and is more flexible than shared memory but may + slow down your system unless the mapped files are configured to reside on a fast or RAM based + filesystem which will normally be the case by default. + e.g. --enable-mmap=yes or --disable-mmap]) +) +if test "$ENABLE_MMAP" == "yes"; then + AC_DEFINE(ZM_MEM_MAPPED,1,"Whether to use mapped rather than shared memory") +else + AC_DEFINE(ZM_MEM_MAPPED,0,"Whether to use mapped rather than shared memory") +fi +AC_SUBST(ENABLE_MMAP) + +# Compiler +AC_LANG_CPLUSPLUS + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_MAKE_SET + +# Checks for typedefs, structures, and compiler characteristics. +AC_HEADER_STDBOOL +AC_C_CONST +AC_TYPE_UID_T +AC_C_INLINE +AC_TYPE_MODE_T +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_STRUCT_TM +AC_TYPE_SIGNAL + +AC_CHECK_TYPES(siginfo_t,,,[#include ]) +AC_CHECK_TYPES(struct sigcontext,,,[#include ]) +AC_CHECK_MEMBERS([struct sigcontext.eip],,,[#include ]) +AC_CHECK_TYPES(ucontext_t,,,[#include ]) + +# Checks for library functions. +AC_PROG_GCC_TRADITIONAL +AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_FUNC_SELECT_ARGTYPES +AC_FUNC_STAT +AC_FUNC_STRFTIME +AC_FUNC_STRTOD +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([gethostbyname gethostname gettimeofday memmove memset mkdir munmap posix_memalign putenv select sendfile socket sqrt strcasecmp strchr strcspn strerror strncasecmp strrchr strsignal strspn strstr strtol strtoull]) +AC_CHECK_FUNCS([syscall sleep usleep ioctl ioctlsocket sigaction]) + +# Other programs +AC_CHECK_PROG(OPT_FFMPEG,ffmpeg,yes,no) +AC_PATH_PROG(PATH_FFMPEG,ffmpeg) +AC_CHECK_PROG(OPT_NETPBM,pnmscale,yes,no) +AC_PATH_PROG(PATH_NETPBM,pnmscale) +if test "$OPT_NETPBM" == "yes"; then +PATH_NETPBM=`dirname $PATH_NETPBM` +fi + +# Checks for libraries. +AC_CHECK_LIB(mysqlclient,mysql_init,,AC_MSG_ERROR(zm requires libmysqlclient.a)) +AC_CHECK_LIB(jpeg,jpeg_start_compress,,AC_MSG_ERROR(zm requires libjpeg.a)) +AC_CHECK_LIB(pthread,pthread_create,,AC_MSG_ERROR(zm requires libpthread.a)) +AC_CHECK_LIB(dl,dlsym,,AC_MSG_ERROR(zm requires libdl.a)) +if test "$ZM_SSL_LIB" == "openssl"; then +AC_CHECK_HEADERS(openssl/md5.h,,AC_MSG_WARN(zm requires openssl/md5.h header to be installed for openssl),) +AC_CHECK_LIB(crypto,MD5,,AC_MSG_WARN([libcrypto.a is required for authenticated streaming - use ZM_SSL_LIB option to select gnutls instead])) +else +AC_CHECK_HEADERS(gnutls/openssl.h,AC_SUBST(ZM_HAS_GNUTLS_OPENSSL,1),AC_SUBST(ZM_HAS_GNUTLS_OPENSSL,0),) +AC_CHECK_HEADERS(gnutls/gnutls.h,AC_SUBST(ZM_HAS_GNUTLS,1),AC_SUBST(ZM_HAS_GNUTLS,0),) +if test "$ZM_HAS_GNUTLS_OPENSSL" == "0" && test "$ZM_HAS_GNUTLS" == "0"; then +AC_MSG_WARN(gnutls is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead) +fi +AC_CHECK_HEADERS(gcrypt.h,,AC_MSG_WARN(zm requires libgcrypt header to be installed for gnutls),) +AC_CHECK_LIB(gcrypt,gcry_check_version,,AC_MSG_WARN([libgcrypt.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead])) +AC_CHECK_LIB(gnutls,gnutls_fingerprint,,AC_MSG_WARN([libgnutls.a is required for authenticated streaming - use ZM_SSL_LIB option to select openssl instead])) +fi +AC_CHECK_LIB(pcre,pcre_compile,,AC_MSG_WARN(libpcre.a may be required for remote/network camera support)) +AC_CHECK_LIB(z,zlibVersion) +AC_CHECK_LIB(x264,x264_predict_16x16_init) +AC_CHECK_LIB(avutil,av_malloc,,AC_MSG_WARN(libavutil.a may be required for MPEG streaming)) +# Don't bother to warn about this one +AC_CHECK_LIB(avcore,av_image_copy,,) +AC_CHECK_LIB(avcodec,avcodec_version,,AC_MSG_WARN(libavcodec.a is required for MPEG streaming)) +AC_CHECK_LIB(avformat,avformat_version,,AC_MSG_WARN(libavformat.a is required for MPEG streaming)) +#AC_CHECK_LIB(avcodec,avcodec_open,,AC_MSG_WARN(libavcodec.a is required for MPEG streaming)) +#AC_CHECK_LIB(avformat,av_new_stream,,AC_MSG_WARN(libavformat.a is required for MPEG streaming)) +AC_CHECK_LIB(avdevice,avdevice_register_all,,AC_MSG_WARN(libavdevice.a may be required for MPEG streaming)) +AC_CHECK_LIB(swscale,sws_scale,,,-lswscale) +AC_CHECK_LIB(bz2,BZ2_bzCompress,,AC_MSG_WARN(zm requires libbz2.a for recent versions of ffmpeg)) +AC_CHECK_LIB(z,compress,,) + +# Checks for header files. +AC_FUNC_ALLOCA +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h limits.h memory.h stddef.h stdlib.h string.h strings.h sys/param.h sys/time.h syslog.h unistd.h values.h]) +AC_CHECK_HEADERS([netdb.h netinet/in.h arpa/inet.h sys/ioctl.h sys/socket.h sys/un.h glob.h sys/sendfile.h]) +AC_CHECK_HEADERS(execinfo.h,,,) +AC_CHECK_HEADERS(syscall.h,,,) +AC_CHECK_HEADERS(pthread.h,,,) +AC_CHECK_HEADERS(linux/videodev.h,AC_SUBST(ZM_HAS_V4L1,1),AC_SUBST(ZM_HAS_V4L1,0),) +AC_CHECK_HEADERS(linux/videodev2.h,AC_SUBST(ZM_HAS_V4L2,1),AC_SUBST(ZM_HAS_V4L2,0),) +if test "$ZM_HAS_V4L1" == "1" || test "$ZM_HAS_V4L2" == "1"; then +AC_SUBST(ZM_HAS_V4L,1) +else +AC_SUBST(ZM_HAS_V4L,0) +AC_MSG_WARN(zm requires Video4Linux or Video4Linux2 to be installed for analog or USB camera support) +fi +AC_CHECK_HEADERS(jpeglib.h,,AC_MSG_ERROR(zm requires libjpeg headers to be installed),) +AC_CHECK_HEADERS(mysql/mysql.h,,AC_MSG_ERROR(zm requires MySQL headers - check that MySQL development packages are installed),) +AC_CHECK_HEADERS(libavutil/avutil.h,,,) +AC_CHECK_HEADERS(libavcodec/avcodec.h,,,) +AC_CHECK_HEADERS(libavformat/avformat.h,,,) +AC_CHECK_HEADERS(libswscale/swscale.h,,,) +AC_CHECK_HEADERS(pcre/pcre.h,AC_SUBST(ZM_PCRE,"1"),,) +AC_CHECK_HEADERS(pcre.h,AC_SUBST(ZM_PCRE,"1"),,) +if test "$ENABLE_MMAP" == "yes"; then +AC_CHECK_HEADERS(sys/mman.h,,,) +AC_CHECK_HEADERS(fcntl.h,,,) +else +AC_CHECK_HEADERS(sys/ipc.h,,,) +AC_CHECK_HEADERS(sys/shm.h,,,) +fi +AC_CHECK_HEADERS(zlib.h,,,) + +AC_CHECK_DECLS(round,,,[#include ]) +if test "$ZM_SSL_LIB" == "openssl"; then +AC_CHECK_DECLS(MD5,,AC_MSG_ERROR([zm requires openssl/md5.h - use ZM_SSL_LIB option to select gnutls instead]),[#include +#include ]) +else +if test "$ZM_HAS_GNUTLS_OPENSSL" == "1"; then +AC_CHECK_DECLS(MD5,,AC_MSG_ERROR([zm requires gnutls/openssl.h - use ZM_SSL_LIB option to select openssl instead]),[#include +#include ]) +else +AC_CHECK_DECLS(gnutls_fingerprint,,AC_MSG_ERROR([zm requires gnutls/gnutls.h - use ZM_SSL_LIB option to select openssl instead]),[#include +#include ]) +fi +fi +AC_CHECK_DECLS(backtrace,,,[#include ]) + +AC_SUBST(LDFLAGS) + +AC_PROG_PERL_VERSION(5.6.0) + +# Compulsory perl modules +AC_PROG_PERL_MODULES(Sys::Syslog,,AC_MSG_ERROR(zm requires SYS:Syslog)) +AC_PROG_PERL_MODULES(DBI,,AC_MSG_ERROR(zm requires DBI)) +AC_PROG_PERL_MODULES(DBD::mysql,,AC_MSG_ERROR(zm requires DBD::mysql)) +AC_PROG_PERL_MODULES(Getopt::Long,,AC_MSG_ERROR(zm requires Getopt::Long)) +AC_PROG_PERL_MODULES(Time::HiRes,,AC_MSG_ERROR(zm requires Time::HiRes)) +AC_PROG_PERL_MODULES(Date::Manip,,AC_MSG_ERROR(zm requires Date::Manip)) +AC_PROG_PERL_MODULES(LWP::UserAgent,,AC_MSG_ERROR(zm requires LWP::UserAgent)) +AC_PROG_PERL_MODULES(ExtUtils::MakeMaker,,AC_MSG_ERROR(zm requires ExtUtils::MakeMaker)) +if test "$ENABLE_MMAP" == "yes"; then +AC_PROG_PERL_MODULES(Sys::Mmap,,AC_MSG_ERROR(zm requires Sys::Mmap for mapped memory - set --enable-mmap=no to use IPC shared memory instead)) +fi + +# Optional perl modules +AC_PROG_PERL_MODULES(Module::Load,,AC_MSG_WARN(Module::Load is required for PTZ camera control)) +AC_PROG_PERL_MODULES(Device::SerialPort,,AC_MSG_WARN(Device::SerialPort is required for RS232/RS485 PTZ camera control)) +AC_PROG_PERL_MODULES(Net::FTP,,AC_MSG_WARN(Net::FTP is required for automatic event uploading using ftp)) +AC_PROG_PERL_MODULES(Net::SFTP::Foreign,,AC_MSG_WARN(Net::SFTP::Foreign is required for automatic event uploading using sftp)) +AC_PROG_PERL_MODULES(Expect,,AC_MSG_WARN(Expect is required for automatic event uploading using sftp)) +AC_PROG_PERL_MODULES(Archive::Tar,,AC_MSG_WARN(Archive::Tar may be required for automatic event uploading)) +AC_PROG_PERL_MODULES(Archive::Zip,,AC_MSG_WARN(Archive::Zip may be required for automatic event uploading)) +AC_PROG_PERL_MODULES(Net::SMTP,,AC_MSG_WARN(Net::SMTP may be required for automatic event email notification)) +AC_PROG_PERL_MODULES(MIME::Lite,,AC_MSG_WARN(MIME::Lite may be required for automatic event email notification)) +AC_PROG_PERL_MODULES(MIME::Entity,,AC_MSG_WARN(MIME::Entity may be required for automatic event email notification)) +AC_PROG_PERL_MODULES(X10::ActiveHome,,AC_MSG_WARN(X10::ActiveHome is required for X.10 support)) + +AC_DEFINE_DIR([BINDIR],[bindir],[Expanded binary directory]) +AC_DEFINE_DIR([LIBDIR],[libdir],[Expanded library directory]) +AC_SUBST(ZM_PID,"$ZM_RUNDIR/zm.pid") +AC_DEFINE_DIR([SYSCONFDIR],[sysconfdir],[Expanded configuration directory]) +AC_SUBST(ZM_CONFIG,"$SYSCONFDIR/zm.conf") + +# Slight hack for non-standard perl install paths +if test "$prefix" != "NONE"; then + PERL_SITE_PREFIX=`perl -V:siteprefix | sed -e "s/.*='\(.*\)';/\1/"` + PERL_SITE_LIB=`perl -V:installsitelib | sed -e "s/.*='\(.*\)';/\1/"` + PERL_LIB_PATH=`echo $PERL_SITE_LIB | sed -e "s|^$PERL_SITE_PREFIX||"` + EXTRA_PERL_LIB="use lib '$prefix$PERL_LIB_PATH'; # Include custom perl install path" + PERL_MM_PARMS="PREFIX=$prefix" +else + EXTRA_PERL_LIB="# Include from system perl paths only" + PERL_MM_PARMS= +fi +AC_SUBST(PERL_MM_PARMS) +AC_SUBST(EXTRA_PERL_LIB) + +AC_CONFIG_FILES([Makefile zm.conf zmconfgen.pl db/Makefile db/zm_create.sql misc/Makefile misc/apache.conf misc/logrotate.conf misc/syslog.conf scripts/Makefile scripts/zm scripts/zmaudit.pl scripts/zmcontrol.pl scripts/zmdc.pl scripts/zmfilter.pl scripts/zmpkg.pl scripts/zmtrack.pl scripts/zmtrigger.pl scripts/zmupdate.pl scripts/zmvideo.pl scripts/zmwatch.pl scripts/zmx10.pl scripts/zmdbbackup scripts/zmdbrestore scripts/zmeventdump scripts/zmlogrotate.conf scripts/ZoneMinder/lib/ZoneMinder/Base.pm scripts/ZoneMinder/lib/ZoneMinder/Config.pm scripts/ZoneMinder/lib/ZoneMinder/Memory.pm scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm src/Makefile src/zm_config.h web/Makefile web/ajax/Makefile web/css/Makefile web/graphics/Makefile web/includes/Makefile web/includes/config.php web/js/Makefile web/lang/Makefile web/skins/Makefile web/skins/classic/Makefile web/skins/classic/ajax/Makefile web/skins/classic/css/Makefile web/skins/classic/graphics/Makefile web/skins/classic/includes/Makefile web/skins/classic/js/Makefile web/skins/classic/lang/Makefile web/skins/classic/views/Makefile web/skins/classic/views/css/Makefile web/skins/classic/views/js/Makefile web/skins/mobile/Makefile web/skins/mobile/ajax/Makefile web/skins/mobile/css/Makefile web/skins/mobile/graphics/Makefile web/skins/mobile/includes/Makefile web/skins/mobile/lang/Makefile web/skins/mobile/views/Makefile web/skins/mobile/views/css/Makefile web/tools/Makefile web/tools/mootools/Makefile web/views/Makefile web/skins/xml/Makefile web/skins/xml/views/Makefile web/skins/xml/includes/Makefile]) + +# Create the definitions for compilation and defaults for the database +AC_CONFIG_COMMANDS([src/zm_config_defines.h],[perl ./zmconfgen.pl]) +# Manually generate the perl Makefile maker +AC_CONFIG_COMMANDS([scripts/ZoneMinder/Makefile],[(cd scripts/ZoneMinder; echo "perl Makefile.PL $PERL_MM_PARMS"; perl Makefile.PL $PERL_MM_PARMS)],[PERL_MM_PARMS=$PERL_MM_PARMS]) + +AC_OUTPUT diff --git a/db/Makefile.am b/db/Makefile.am new file mode 100644 index 000000000..384fe7e47 --- /dev/null +++ b/db/Makefile.am @@ -0,0 +1,44 @@ +AUTOMAKE_OPTIONS = gnu + +EXTRA_DIST = \ + zm_create.sql.in \ + zm_update-0.0.1.sql \ + zm_update-0.9.7.sql \ + zm_update-0.9.8.sql \ + zm_update-0.9.9.sql \ + zm_update-0.9.10.sql \ + zm_update-0.9.11.sql \ + zm_update-0.9.12.sql \ + zm_update-0.9.13.sql \ + zm_update-0.9.15.sql \ + zm_update-0.9.16.sql \ + zm_update-1.17.1.sql \ + zm_update-1.17.2.sql \ + zm_update-1.18.0.sql \ + zm_update-1.18.1.sql \ + zm_update-1.19.0.sql \ + zm_update-1.19.1.sql \ + zm_update-1.19.2.sql \ + zm_update-1.19.3.sql \ + zm_update-1.19.4.sql \ + zm_update-1.19.5.sql \ + zm_update-1.20.0.sql \ + zm_update-1.20.1.sql \ + zm_update-1.21.0.sql \ + zm_update-1.21.1.sql \ + zm_update-1.21.2.sql \ + zm_update-1.21.3.sql \ + zm_update-1.21.4.sql \ + zm_update-1.22.0.sql \ + zm_update-1.22.1.sql \ + zm_update-1.22.2.sql \ + zm_update-1.22.3.sql \ + zm_update-1.23.0.sql \ + zm_update-1.23.1.sql \ + zm_update-1.23.2.sql \ + zm_update-1.23.3.sql \ + zm_update-1.24.0.sql \ + zm_update-1.24.1.sql \ + zm_update-1.24.2.sql \ + zm_update-1.24.3.sql \ + zm_update-1.24.4.sql diff --git a/db/Makefile.in b/db/Makefile.in new file mode 100644 index 000000000..c58725cd2 --- /dev/null +++ b/db/Makefile.in @@ -0,0 +1,439 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = db +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/zm_create.sql.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = zm_create.sql +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +EXTRA_DIST = \ + zm_create.sql.in \ + zm_update-0.0.1.sql \ + zm_update-0.9.7.sql \ + zm_update-0.9.8.sql \ + zm_update-0.9.9.sql \ + zm_update-0.9.10.sql \ + zm_update-0.9.11.sql \ + zm_update-0.9.12.sql \ + zm_update-0.9.13.sql \ + zm_update-0.9.15.sql \ + zm_update-0.9.16.sql \ + zm_update-1.17.1.sql \ + zm_update-1.17.2.sql \ + zm_update-1.18.0.sql \ + zm_update-1.18.1.sql \ + zm_update-1.19.0.sql \ + zm_update-1.19.1.sql \ + zm_update-1.19.2.sql \ + zm_update-1.19.3.sql \ + zm_update-1.19.4.sql \ + zm_update-1.19.5.sql \ + zm_update-1.20.0.sql \ + zm_update-1.20.1.sql \ + zm_update-1.21.0.sql \ + zm_update-1.21.1.sql \ + zm_update-1.21.2.sql \ + zm_update-1.21.3.sql \ + zm_update-1.21.4.sql \ + zm_update-1.22.0.sql \ + zm_update-1.22.1.sql \ + zm_update-1.22.2.sql \ + zm_update-1.22.3.sql \ + zm_update-1.23.0.sql \ + zm_update-1.23.1.sql \ + zm_update-1.23.2.sql \ + zm_update-1.23.3.sql \ + zm_update-1.24.0.sql \ + zm_update-1.24.1.sql \ + zm_update-1.24.2.sql \ + zm_update-1.24.3.sql \ + zm_update-1.24.4.sql + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu db/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu db/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +zm_create.sql: $(top_builddir)/config.status $(srcdir)/zm_create.sql.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/db/zm_create.sql b/db/zm_create.sql new file mode 100644 index 000000000..fa91d3e35 --- /dev/null +++ b/db/zm_create.sql @@ -0,0 +1,934 @@ +-- MySQL dump 10.9 +-- +-- Host: localhost Database: zm +-- ------------------------------------------------------ +-- Server version 4.1.16-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `zm` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `zm`; + +USE `zm`; + +-- +-- Table structure for table `Config` +-- + +DROP TABLE IF EXISTS `Config`; +CREATE TABLE `Config` ( + `Id` smallint(5) unsigned NOT NULL default '0', + `Name` varchar(32) NOT NULL default '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `DefaultValue` tinytext, + `Hint` tinytext, + `Pattern` tinytext, + `Format` tinytext, + `Prompt` tinytext, + `Help` text, + `Category` varchar(32) NOT NULL default '', + `Readonly` tinyint(3) unsigned NOT NULL default '0', + `Requires` text, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `ControlPresets` +-- + +DROP TABLE IF EXISTS `ControlPresets`; +CREATE TABLE `ControlPresets` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Preset` int(10) unsigned NOT NULL default '0', + `Label` varchar(64) NOT NULL default '', + PRIMARY KEY (`MonitorId`,`Preset`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Controls` +-- + +DROP TABLE IF EXISTS `Controls`; +CREATE TABLE `Controls` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote') NOT NULL default 'Local', + `Protocol` varchar(64) default NULL, + `CanWake` tinyint(3) unsigned NOT NULL default '0', + `CanSleep` tinyint(3) unsigned NOT NULL default '0', + `CanReset` tinyint(3) unsigned NOT NULL default '0', + `CanZoom` tinyint(3) unsigned NOT NULL default '0', + `CanAutoZoom` tinyint(3) unsigned NOT NULL default '0', + `CanZoomAbs` tinyint(3) unsigned NOT NULL default '0', + `CanZoomRel` tinyint(3) unsigned NOT NULL default '0', + `CanZoomCon` tinyint(3) unsigned NOT NULL default '0', + `MinZoomRange` int(10) unsigned default NULL, + `MaxZoomRange` int(10) unsigned default NULL, + `MinZoomStep` int(10) unsigned default NULL, + `MaxZoomStep` int(10) unsigned default NULL, + `HasZoomSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinZoomSpeed` int(10) unsigned default NULL, + `MaxZoomSpeed` int(10) unsigned default NULL, + `CanFocus` tinyint(3) unsigned NOT NULL default '0', + `CanAutoFocus` tinyint(3) unsigned NOT NULL default '0', + `CanFocusAbs` tinyint(3) unsigned NOT NULL default '0', + `CanFocusRel` tinyint(3) unsigned NOT NULL default '0', + `CanFocusCon` tinyint(3) unsigned NOT NULL default '0', + `MinFocusRange` int(10) unsigned default NULL, + `MaxFocusRange` int(10) unsigned default NULL, + `MinFocusStep` int(10) unsigned default NULL, + `MaxFocusStep` int(10) unsigned default NULL, + `HasFocusSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinFocusSpeed` int(10) unsigned default NULL, + `MaxFocusSpeed` int(10) unsigned default NULL, + `CanIris` tinyint(3) unsigned NOT NULL default '0', + `CanAutoIris` tinyint(3) unsigned NOT NULL default '0', + `CanIrisAbs` tinyint(3) unsigned NOT NULL default '0', + `CanIrisRel` tinyint(3) unsigned NOT NULL default '0', + `CanIrisCon` tinyint(3) unsigned NOT NULL default '0', + `MinIrisRange` int(10) unsigned default NULL, + `MaxIrisRange` int(10) unsigned default NULL, + `MinIrisStep` int(10) unsigned default NULL, + `MaxIrisStep` int(10) unsigned default NULL, + `HasIrisSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinIrisSpeed` int(10) unsigned default NULL, + `MaxIrisSpeed` int(10) unsigned default NULL, + `CanGain` tinyint(3) unsigned NOT NULL default '0', + `CanAutoGain` tinyint(3) unsigned NOT NULL default '0', + `CanGainAbs` tinyint(3) unsigned NOT NULL default '0', + `CanGainRel` tinyint(3) unsigned NOT NULL default '0', + `CanGainCon` tinyint(3) unsigned NOT NULL default '0', + `MinGainRange` int(10) unsigned default NULL, + `MaxGainRange` int(10) unsigned default NULL, + `MinGainStep` int(10) unsigned default NULL, + `MaxGainStep` int(10) unsigned default NULL, + `HasGainSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinGainSpeed` int(10) unsigned default NULL, + `MaxGainSpeed` int(10) unsigned default NULL, + `CanWhite` tinyint(3) unsigned NOT NULL default '0', + `CanAutoWhite` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteAbs` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteRel` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteCon` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteRange` int(10) unsigned default NULL, + `MaxWhiteRange` int(10) unsigned default NULL, + `MinWhiteStep` int(10) unsigned default NULL, + `MaxWhiteStep` int(10) unsigned default NULL, + `HasWhiteSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteSpeed` int(10) unsigned default NULL, + `MaxWhiteSpeed` int(10) unsigned default NULL, + `HasPresets` tinyint(3) unsigned NOT NULL default '0', + `NumPresets` tinyint(3) unsigned NOT NULL default '0', + `HasHomePreset` tinyint(3) unsigned NOT NULL default '0', + `CanSetPresets` tinyint(3) unsigned NOT NULL default '0', + `CanMove` tinyint(3) unsigned NOT NULL default '0', + `CanMoveDiag` tinyint(3) unsigned NOT NULL default '0', + `CanMoveMap` tinyint(3) unsigned NOT NULL default '0', + `CanMoveAbs` tinyint(3) unsigned NOT NULL default '0', + `CanMoveRel` tinyint(3) unsigned NOT NULL default '0', + `CanMoveCon` tinyint(3) unsigned NOT NULL default '0', + `CanPan` tinyint(3) unsigned NOT NULL default '0', + `MinPanRange` int(10) default NULL, + `MaxPanRange` int(10) default NULL, + `MinPanStep` int(10) default NULL, + `MaxPanStep` int(10) default NULL, + `HasPanSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinPanSpeed` int(10) default NULL, + `MaxPanSpeed` int(10) default NULL, + `HasTurboPan` tinyint(3) unsigned NOT NULL default '0', + `TurboPanSpeed` int(10) default NULL, + `CanTilt` tinyint(3) unsigned NOT NULL default '0', + `MinTiltRange` int(10) default NULL, + `MaxTiltRange` int(10) default NULL, + `MinTiltStep` int(10) default NULL, + `MaxTiltStep` int(10) default NULL, + `HasTiltSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinTiltSpeed` int(10) default NULL, + `MaxTiltSpeed` int(10) default NULL, + `HasTurboTilt` tinyint(3) unsigned NOT NULL default '0', + `TurboTiltSpeed` int(10) default NULL, + `CanAutoScan` tinyint(3) unsigned NOT NULL default '0', + `NumScanPaths` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Devices` +-- + +DROP TABLE IF EXISTS `Devices`; +CREATE TABLE `Devices` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` tinytext NOT NULL, + `Type` enum('X10') NOT NULL default 'X10', + `KeyString` varchar(32) NOT NULL default '', + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Events` +-- + +DROP TABLE IF EXISTS `Events`; +CREATE TABLE `Events` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Cause` varchar(32) NOT NULL default '', + `StartTime` datetime default NULL, + `EndTime` datetime default NULL, + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Length` decimal(10,2) NOT NULL default '0.00', + `Frames` int(10) unsigned default NULL, + `AlarmFrames` int(10) unsigned default NULL, + `TotScore` int(10) unsigned NOT NULL default '0', + `AvgScore` smallint(5) unsigned default '0', + `MaxScore` smallint(5) unsigned default '0', + `Archived` tinyint(3) unsigned NOT NULL default '0', + `Videoed` tinyint(3) unsigned NOT NULL default '0', + `Uploaded` tinyint(3) unsigned NOT NULL default '0', + `Emailed` tinyint(3) unsigned NOT NULL default '0', + `Messaged` tinyint(3) unsigned NOT NULL default '0', + `Executed` tinyint(3) unsigned NOT NULL default '0', + `Notes` text, + PRIMARY KEY (`Id`,`MonitorId`), + KEY `MonitorId` (`MonitorId`), + KEY `StartTime` (`StartTime`), + KEY `Frames` (`Frames`), + KEY `Archived` (`Archived`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Filters` +-- + +DROP TABLE IF EXISTS `Filters`; +CREATE TABLE `Filters` ( + `Name` varchar(64) NOT NULL default '', + `Query` text NOT NULL, + `AutoArchive` tinyint(3) unsigned NOT NULL default '0', + `AutoVideo` tinyint(3) unsigned NOT NULL default '0', + `AutoUpload` tinyint(3) unsigned NOT NULL default '0', + `AutoEmail` tinyint(3) unsigned NOT NULL default '0', + `AutoMessage` tinyint(3) unsigned NOT NULL default '0', + `AutoExecute` tinyint(3) unsigned NOT NULL default '0', + `AutoExecuteCmd` tinytext, + `AutoDelete` tinyint(3) unsigned NOT NULL default '0', + `Background` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`Name`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Frames` +-- + +DROP TABLE IF EXISTS `Frames`; +CREATE TABLE `Frames` ( + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `Type` enum('Normal','Bulk','Alarm') NOT NULL default 'Normal', + `TimeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `Delta` decimal(8,2) NOT NULL default '0.00', + `Score` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`EventId`,`FrameId`), + KEY `Type` (`Type`), + KEY `TimeStamp` (`TimeStamp`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Groups` +-- + +DROP TABLE IF EXISTS `Groups`; +CREATE TABLE `Groups` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Logs` +-- +CREATE TABLE `Logs` ( + `TimeKey` decimal(16,6) NOT NULL, + `Component` varchar(32) NOT NULL, + `Pid` smallint(6) DEFAULT NULL, + `Level` tinyint(3) NOT NULL, + `Code` char(3) NOT NULL, + `Message` varchar(255) NOT NULL, + `File` varchar(255) DEFAULT NULL, + `Line` smallint(5) unsigned DEFAULT NULL, + KEY `TimeKey` (`TimeKey`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `MonitorPresets` +-- + +DROP TABLE IF EXISTS `MonitorPresets`; +CREATE TABLE `MonitorPresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Device` tinytext, + `Channel` tinyint(3) unsigned default NULL, + `Format` int(10) unsigned default NULL, + `Protocol` varchar(16) default NULL, + `Method` varchar(16) default NULL, + `Host` varchar(64) default NULL, + `Port` varchar(8) default NULL, + `Path` varchar(255) default NULL, + `SubPath` varchar(64) default NULL, + `Width` smallint(5) unsigned default NULL, + `Height` smallint(5) unsigned default NULL, + `Palette` int(10) unsigned default NULL, + `MaxFPS` decimal(5,2) default NULL, + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` varchar(16) default NULL, + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Monitors` +-- + +DROP TABLE IF EXISTS `Monitors`; +CREATE TABLE `Monitors` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `LinkedMonitors` varchar(255) NOT NULL default '', + `Triggers` set('X10') NOT NULL default '', + `Device` varchar(64) NOT NULL default '', + `Channel` tinyint(3) unsigned NOT NULL default '0', + `Format` int(10) unsigned NOT NULL default '0', + `Protocol` varchar(16) NOT NULL default '', + `Method` varchar(16) NOT NULL default '', + `Host` varchar(64) NOT NULL default '', + `Port` varchar(8) NOT NULL default '', + `SubPath` varchar(64) NOT NULL default '', + `Path` varchar(255) NOT NULL default '', + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Colours` tinyint(3) unsigned NOT NULL default '1', + `Palette` int(10) unsigned NOT NULL default '0', + `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', + `Deinterlacing` int(10) unsigned NOT NULL default '0', + `Brightness` mediumint(7) NOT NULL default '-1', + `Contrast` mediumint(7) NOT NULL default '-1', + `Hue` mediumint(7) NOT NULL default '-1', + `Colour` mediumint(7) NOT NULL default '-1', + `EventPrefix` varchar(32) NOT NULL default 'Event-', + `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S', + `LabelX` smallint(5) unsigned NOT NULL default '0', + `LabelY` smallint(5) unsigned NOT NULL default '0', + `ImageBufferCount` smallint(5) unsigned NOT NULL default '100', + `WarmupCount` smallint(5) unsigned NOT NULL default '25', + `PreEventCount` smallint(5) unsigned NOT NULL default '10', + `PostEventCount` smallint(5) unsigned NOT NULL default '10', + `StreamReplayBuffer` int(10) unsigned NOT NULL default '1000', + `AlarmFrameCount` smallint(5) unsigned NOT NULL default '1', + `SectionLength` int(10) unsigned NOT NULL default '600', + `FrameSkip` smallint(5) unsigned NOT NULL default '0', + `MaxFPS` decimal(5,2) default NULL, + `AlarmMaxFPS` decimal(5,2) default NULL, + `FPSReportInterval` smallint(5) unsigned NOT NULL default '250', + `RefBlendPerc` tinyint(3) unsigned NOT NULL default '10', + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` int(10) unsigned NOT NULL default '0', + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `AutoStopTimeout` decimal(5,2) default NULL, + `TrackMotion` tinyint(3) unsigned NOT NULL default '0', + `TrackDelay` smallint(5) unsigned NOT NULL default '0', + `ReturnLocation` tinyint(3) NOT NULL default '-1', + `ReturnDelay` smallint(5) unsigned NOT NULL default '0', + `DefaultView` enum('Events','Control') NOT NULL default 'Events', + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + `SignalCheckColour` varchar(32) NOT NULL default '#0000BE', + `WebColour` varchar(32) NOT NULL default 'red', + `Sequence` smallint(5) unsigned default NULL, + `UsedPl` varchar(88) NOT NULL default '', + `DoNativeMotDet` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `PluginsConfig` +-- + +DROP TABLE IF EXISTS `PluginsConfig`; +CREATE TABLE `PluginsConfig` ( + `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Name` varchar(32) NOT NULL DEFAULT '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `Choices` text NOT NULL, + `MonitorId` int(10) unsigned NOT NULL, + `ZoneId` int(10) unsigned NOT NULL, + `pluginName` tinytext NOT NULL, + PRIMARY KEY (`Id`), + KEY `ZoneId` (`ZoneId`), + KEY `MonitorId` (`MonitorId`), + KEY `Name` (`Name`), + FULLTEXT KEY `pluginName` (`pluginName`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; + + +-- +-- Table structure for table `States` +-- + +DROP TABLE IF EXISTS `States`; +CREATE TABLE `States` ( + `Name` varchar(64) NOT NULL default '', + `Definition` text NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Stats` +-- + +DROP TABLE IF EXISTS `Stats`; +CREATE TABLE `Stats` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `ZoneId` int(10) unsigned NOT NULL default '0', + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `PixelDiff` tinyint(3) unsigned NOT NULL default '0', + `AlarmPixels` int(10) unsigned NOT NULL default '0', + `FilterPixels` int(10) unsigned NOT NULL default '0', + `BlobPixels` int(10) unsigned NOT NULL default '0', + `Blobs` smallint(5) unsigned NOT NULL default '0', + `MinBlobSize` int(10) unsigned NOT NULL default '0', + `MaxBlobSize` int(10) unsigned NOT NULL default '0', + `MinX` smallint(5) unsigned NOT NULL default '0', + `MaxX` smallint(5) unsigned NOT NULL default '0', + `MinY` smallint(5) unsigned NOT NULL default '0', + `MaxY` smallint(5) unsigned NOT NULL default '0', + `Score` smallint(5) unsigned NOT NULL default '0', + KEY `EventId` (`EventId`), + KEY `MonitorId` (`MonitorId`), + KEY `ZoneId` (`ZoneId`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `TriggersX10` +-- + +DROP TABLE IF EXISTS `TriggersX10`; +CREATE TABLE `TriggersX10` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Activation` varchar(32) default NULL, + `AlarmInput` varchar(32) default NULL, + `AlarmOutput` varchar(32) default NULL, + PRIMARY KEY (`MonitorId`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Users` +-- + +DROP TABLE IF EXISTS `Users`; +CREATE TABLE `Users` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '', + `Password` varchar(64) NOT NULL default '', + `Language` varchar(8) NOT NULL default '', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `Stream` enum('None','View') NOT NULL default 'None', + `Events` enum('None','View','Edit') NOT NULL default 'None', + `Control` enum('None','View','Edit') NOT NULL default 'None', + `Monitors` enum('None','View','Edit') NOT NULL default 'None', + `Devices` enum('None','View','Edit') NOT NULL default 'None', + `System` enum('None','View','Edit') NOT NULL default 'None', + `MaxBandwidth` varchar(16) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`), + UNIQUE KEY `UC_Username` (`Username`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `ZonePresets` +-- + +DROP TABLE IF EXISTS `ZonePresets`; +CREATE TABLE `ZonePresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=MyISAM; + +-- +-- Table structure for table `Zones` +-- + +DROP TABLE IF EXISTS `Zones`; +CREATE TABLE `Zones` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `NumCoords` tinyint(3) unsigned NOT NULL default '0', + `Coords` tinytext NOT NULL, + `Area` int(10) unsigned NOT NULL default '0', + `AlarmRGB` int(10) unsigned default '0', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`), + KEY `MonitorId` (`MonitorId`) +) ENGINE=MyISAM; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- +-- Initial data to be loaded into ZoneMinder database +-- + +-- +-- Create a default admin user. +-- +insert into Users values ('','admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','Edit','',''); + +-- +-- Add a sample filter to purge the oldest 5 events when the disk is 95% full, delete is disabled though +-- +insert into Filters values ('PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":5,"sort_asc":1}',0,0,0,0,0,0,'',1,0); + +-- +-- Add in some sample control protocol definitions +-- +insert into Controls values (1,'Pelco-D','Local','PelcoD',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (2,'Pelco-P','Local','PelcoP',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (3,'Sony VISCA','Local','Visca',1,1,0,1,0,0,0,1,0,16384,10,4000,1,1,6,1,1,1,0,1,0,1536,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,3,1,1,1,1,0,1,1,0,1,-15578,15578,100,10000,1,1,50,1,254,1,-7789,7789,100,5000,1,1,50,1,254,0,0); +INSERT INTO Controls VALUES (4,'Axis API v2','Remote','AxisV2',0,0,0,1,0,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,1,1,1,1,1,0,1,0,1,-360,360,1,90,0,NULL,NULL,0,NULL,1,-360,360,1,90,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (5,'Panasonic IP','Remote','PanasonicIP',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,8,1,1,1,0,1,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (6,'Neu-Fusion NCS370','Remote','Ncs370',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,24,1,0,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); + +-- +-- Add some monitor preset values +-- +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,1,4,NULL,':',100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, multicast','Remote',NULL,NULL,NULL,'rtsp','rtpMulti','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP','Remote',NULL,NULL,NULL,'rtsp','rtpRtsp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','VEO Observer, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Blue Net Video Server, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); + +-- +-- Add some zone preset values +-- +INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',60,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',40,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',20,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',60,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',40,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL,0); + +-- +-- Apply the initial configuration +-- +-- This section is autogenerated by zmconfgen.pl +-- Do not edit this file as any changes will be overwritten +-- + +delete from Config; + +insert into Config set Id = 0, Name = 'ZM_LANG_DEFAULT', Value = 'en_gb', Type = 'string', DefaultValue = 'en_gb', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Default language used by web interface', Help = 'ZoneMinder allows the web interface to use languages other than English if the appropriate language file has been created and is present. This option allows you to change the default language that is used from the shipped language, British English, to another language', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 1, Name = 'ZM_OPT_USE_AUTH', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Authenticate user logins to ZoneMinder', Help = 'ZoneMinder can run in two modes. The simplest is an entirely unauthenticated mode where anyone can access ZoneMinder and perform all tasks. This is most suitable for installations where the web server access is limited in other ways. The other mode enables user accounts with varying sets of permissions. Users must login or authenticate to access ZoneMinder and are limited by their defined permissions.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 2, Name = 'ZM_AUTH_TYPE', Value = 'builtin', Type = 'string', DefaultValue = 'builtin', Hint = 'builtin|remote', Pattern = '(?^i:^([br]))', Format = ' $1 =~ /^b/ ? \"builtin\" : \"remote\" ', Prompt = 'What is used to authenticate ZoneMinder users', Help = 'ZoneMinder can use two methods to authenticate users when running in authenticated mode. The first is a builtin method where ZoneMinder provides facilities for users to log in and maintains track of their identity. The second method allows interworking with other methods such as http basic authentication which passes an independently authentication \'remote\' user via http. In this case ZoneMinder would use the supplied user without additional authentication provided such a user is configured ion ZoneMinder.', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_USE_AUTH=1'; +insert into Config set Id = 3, Name = 'ZM_AUTH_RELAY', Value = 'hashed', Type = 'string', DefaultValue = 'hashed', Hint = 'hashed|plain|none', Pattern = '(?^i:^([hpn]))', Format = ' ($1 =~ /^h/) ? \"hashed\" : ($1 =~ /^p/ ? \"plain\" : \"none\" ) ', Prompt = 'Method used to relay authentication information', Help = 'When ZoneMinder is running in authenticated mode it can pass user details between the web pages and the back end processes. There are two methods for doing this. This first is to use a time limited hashed string which contains no direct username or password details, the second method is to pass the username and passwords around in plaintext. This method is not recommend except where you do not have the md5 libraries available on your system or you have a completely isolated system with no external access. You can also switch off authentication relaying if your system is isolated in other ways.', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_USE_AUTH=1'; +insert into Config set Id = 4, Name = 'ZM_AUTH_HASH_SECRET', Value = '...Change me to something unique...', Type = 'string', DefaultValue = '...Change me to something unique...', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Secret for encoding hashed authentication information', Help = 'When ZoneMinder is running in hashed authenticated mode it is necessary to generate hashed strings containing encrypted sensitive information such as usernames and password. Although these string are reasonably secure the addition of a random secret increases security substantially.', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_USE_AUTH=1;ZM_AUTH_RELAY=hashed'; +insert into Config set Id = 5, Name = 'ZM_AUTH_HASH_IPS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Include IP addresses in the authentication hash', Help = 'When ZoneMinder is running in hashed authenticated mode it can optionally include the requesting IP address in the resultant hash. This adds an extra level of security as only requests from that address may use that authentication key. However in some circumstances, such as access over mobile networks, the requesting address can change for each request which will cause most requests to fail. This option allows you to control whether IP addresses are included in the authentication hash on your system. If you experience intermitent problems with authentication, switching this option off may help.', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_USE_AUTH=1;ZM_AUTH_RELAY=hashed'; +insert into Config set Id = 6, Name = 'ZM_AUTH_HASH_LOGINS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Allow login by authentication hash', Help = 'The normal process for logging into ZoneMinder is via the login screen with username and password. In some circumstances it may be desirable to allow access directly to one or more pages, for instance from a third party application. If this option is enabled then adding an \'auth\' parameter to any request will include a shortcut login bypassing the login screen, if not already logged in. As authentication hashes are time and, optionally, IP limited this can allow short-term access to ZoneMinder screens from other web pages etc. In order to use this the calling application will hae to generate the authentication hash itself and ensure it is valid. If you use this option you should ensure that you have modified the ZM_AUTH_HASH_SECRET to somethign unique to your system.', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_USE_AUTH=1;ZM_AUTH_RELAY=hashed'; +insert into Config set Id = 7, Name = 'ZM_DIR_EVENTS', Value = 'events', Type = 'string', DefaultValue = 'events', Hint = 'directory', Pattern = '(?^:^([a-zA-Z0-9-_.]+)$)', Format = ' $1 ', Prompt = 'Directory where events are stored', Help = 'This is the path to the events directory where all the event images and other miscellaneous files are stored. It is normally given as a subdirectory of the web directory you have specified earlier however if disk space is tight it can reside on another partition in which case you should create a link from that area to the path you give here.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 8, Name = 'ZM_USE_DEEP_STORAGE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use a deep filesystem hierarchy for events', Help = 'Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 9, Name = 'ZM_DIR_IMAGES', Value = 'images', Type = 'string', DefaultValue = 'images', Hint = 'directory', Pattern = '(?^:^([a-zA-Z0-9-_.]+)$)', Format = ' $1 ', Prompt = 'Directory where the images that the ZoneMinder client generates are stored', Help = 'ZoneMinder generates a myriad of images, mosty of which are associated with events. For those that aren\'t this is where they go.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 10, Name = 'ZM_DIR_SOUNDS', Value = 'sounds', Type = 'string', DefaultValue = 'sounds', Hint = 'directory', Pattern = '(?^:^([a-zA-Z0-9-_.]+)$)', Format = ' $1 ', Prompt = 'Directory to the sounds that the ZoneMinder client can use', Help = 'ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where (relative to the web root) to look for this file.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 11, Name = 'ZM_PATH_ZMS', Value = '/cgi-bin/nph-zms', Type = 'string', DefaultValue = '/cgi-bin/nph-zms', Hint = 'relative/path/to/somewhere', Pattern = '(?^:^((?:[^/].*)?)/?$)', Format = ' $1 ', Prompt = 'Web path to zms streaming server', Help = 'The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing \'zms\' to \'nph-zms\'.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 12, Name = 'ZM_COLOUR_JPEG_FILES', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Colourise greyscale JPEG files', Help = 'Cameras that capture in greyscale can write their captured images to jpeg files with a corresponding greyscale colour space. This saves a small amount of disk space over colour ones. However some tools such as ffmpeg either fail to work with this colour space or have to convert it beforehand. Setting this option to yes uses up a little more space but makes creation of MPEG files much faster.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 13, Name = 'ZM_ADD_JPEG_COMMENTS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Add jpeg timestamp annotations as file header comments', Help = 'JPEG files may have a number of extra fields added to the file header. The comment field may have any kind of text added. This options allows you to have the same text that is used to annotate the image additionally included as a file header comment. If you archive event images to other locations this may help you locate images for particular events or times if you use software that can read comment headers.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 14, Name = 'ZM_JPEG_FILE_QUALITY', Value = '70', Type = 'integer', DefaultValue = '70', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Set the JPEG quality setting for the saved event files (1-100)', Help = 'When ZoneMinder detects an event it will save the images associated with that event to files. These files are in the JPEG format and can be viewed or streamed later. This option specifies what image quality should be used to save these files. A higher number means better quality but less compression so will take up more disk space and take longer to view over a slow connection. By contrast a low number means smaller, quicker to view, files but at the price of lower quality images. This setting applies to all images written except if the capture image has caused an alarm and the alarm file quality option is set at a higher value when that is used instead.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 15, Name = 'ZM_JPEG_ALARM_FILE_QUALITY', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Set the JPEG quality setting for the saved event files during an alarm (1-100)', Help = 'This value is equivalent to the regular jpeg file quality setting above except that it only applies to images saved while in an alarm state and then only if this value is set to a higher quality setting than the ordinary file setting. If set to a lower value then it is ignored. Thus leaving it at the default of 0 effectively means to use the regular file quality setting for all saved images. This is to prevent acccidentally saving important images at a worse quality setting.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 16, Name = 'ZM_JPEG_IMAGE_QUALITY', Value = '70', Type = 'integer', DefaultValue = '70', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Set the JPEG quality setting for the streamed \'live\' images (1-100)', Help = 'When viewing a \'live\' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.', Category = 'hidden', Readonly = '0', Requires = ''; +insert into Config set Id = 17, Name = 'ZM_JPEG_STREAM_QUALITY', Value = '70', Type = 'integer', DefaultValue = '70', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Set the JPEG quality setting for the streamed \'live\' images (1-100)', Help = 'When viewing a \'live\' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 18, Name = 'ZM_MPEG_TIMED_FRAMES', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Tag video frames with a timestamp for more realistic streaming', Help = 'When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it\'s capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it\'s \'real\' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 19, Name = 'ZM_MPEG_LIVE_FORMAT', Value = 'swf', Type = 'string', DefaultValue = 'swf', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What format \'live\' video streams are played in', Help = 'When using MPEG mode ZoneMinder can output live video. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of \'asf\' works well under Windows with Windows Media Player but I\'m currently not sure what, if anything, works on a Linux platform. If you find out please let me know! If this option is left blank then live streams will revert to being in motion jpeg format', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 20, Name = 'ZM_MPEG_REPLAY_FORMAT', Value = 'swf', Type = 'string', DefaultValue = 'swf', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What format \'replay\' video streams are played in', Help = 'When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of \'asf\' works well under Windows with Windows Media Player and \'mpg\', or \'avi\' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 21, Name = 'ZM_RAND_STREAM', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Add a random string to prevent caching of streams', Help = 'Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 22, Name = 'ZM_OPT_CAMBOZOLA', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Is the (optional) cambozola java streaming client installed', Help = 'Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don\'t natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 23, Name = 'ZM_PATH_CAMBOZOLA', Value = 'cambozola.jar', Type = 'string', DefaultValue = 'cambozola.jar', Hint = 'relative/path/to/somewhere', Pattern = '(?^:^((?:[^/].*)?)/?$)', Format = ' $1 ', Prompt = 'Web path to (optional) cambozola java streaming client', Help = 'Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don\'t natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. Leave this as \'cambozola.jar\' if cambozola is installed in the same directory as the ZoneMinder web client files.', Category = 'images', Readonly = '0', Requires = 'ZM_OPT_CAMBOZOLA=1'; +insert into Config set Id = 24, Name = 'ZM_RELOAD_CAMBOZOLA', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'After how many seconds should Cambozola be reloaded in live view', Help = 'Cambozola allows for the viewing of streaming MJPEG however it caches the entire stream into cache space on the computer, setting this to a number > 0 will cause it to automatically reload after that many seconds to avoid filling up a hard drive.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 25, Name = 'ZM_TIMESTAMP_ON_CAPTURE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Timestamp images as soon as they are captured', Help = 'ZoneMinder can add a timestamp to images in two ways. The default method, when this option is set, is that each image is timestamped immediately when captured and so the image held in memory is marked right away. The second method does not timestamp the images until they are either saved as part of an event or accessed over the web. The timestamp used in both methods will contain the same time as this is preserved along with the image. The first method ensures that an image is timestamped regardless of any other circumstances but will result in all images being timestamped even those never saved or viewed. The second method necessitates that saved images are copied before being saved otherwise two timestamps perhaps at different scales may be applied. This has the (perhaps) desirable side effect that the timestamp is always applied at the same resolution so an image that has scaling applied will still have a legible and correctly scaled timestamp.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 26, Name = 'ZM_CPU_EXTENSIONS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use advanced CPU extensions to increase performance', Help = 'When advanced processor extensions such as SSE2 or SSSE3 are available, ZoneMinder can use them, which should increase performance and reduce system load. Enabling this option on processors that do not support the advanced processors extensions used by ZoneMinder is harmless and will have no effect.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 27, Name = 'ZM_FAST_IMAGE_BLENDS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use a fast algorithm to blend the reference image', Help = 'To detect alarms ZoneMinder needs to blend the captured image with the stored reference image to update it for comparison with the next image. The reference blend percentage specified for the monitor controls how much the new image affects the reference image. There are two methods that are available for this. If this option is set then fast calculation which does not use any multiplication or division is used. This calculation is extremely fast, however it limits the possible blend percentages to 50%, 25%, 12.5%, 6.25%, 3.25% and 1.5%. Any other blend percentage will be rounded to the nearest possible one. The alternative is to switch this option off and use standard blending instead, which is slower.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 28, Name = 'ZM_OPT_ADAPTIVE_SKIP', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should frame analysis try and be efficient in skipping frames', Help = 'In previous versions of ZoneMinder the analysis daemon would attempt to keep up with the capture daemon by processing the last captured frame on each pass. This would sometimes have the undesirable side-effect of missing a chunk of the initial activity that caused the alarm because the pre-alarm frames would all have to be written to disk and the database before processing the next frame, leading to some delay between the first and second event frames. Setting this option enables a newer adaptive algorithm where the analysis daemon attempts to process as many captured frames as possible, only skipping frames when in danger of the capture daemon overwriting yet to be processed frames. This skip is variable depending on the size of the ring buffer and the amount of space left in it. Enabling this option will give you much better coverage of the beginning of alarms whilst biasing out any skipped frames towards the middle or end of the event. However you should be aware that this will have the effect of making the analysis daemon run somewhat behind the capture daemon during events and for particularly fast rates of capture it is possible for the adaptive algorithm to be overwhelmed and not have time to react to a rapid build up of pending frames and thus for a buffer overrun condition to occur.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 29, Name = 'ZM_BLEND_ALARMED_IMAGES', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Blend alarmed images to update the reference image', Help = 'To detect alarms ZoneMinder compares an image with a reference image which is formed from a composite of the previous images. This option determines whether images that cause events are included in this process. Doing so may increase the precision of the alarmed region but can cause problems if wholescale lighting changes cause alarms as this would not get fed back into the image and an alarm may persist indefinately. A better way to achive the same effect in most cases is to lower substantially the reference blend percentage in specific monitors.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 30, Name = 'ZM_MAX_SUSPEND_TIME', Value = '30', Type = 'integer', DefaultValue = '30', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Maximum time that a monitor may have motion detection suspended', Help = 'ZoneMinder allows monitors to have motion detection to be suspended, for instance while panning a camera. Ordinarily this relies on the operator resuming motion detection afterwards as failure to do so can leave a monitor in a permanently suspended state. This setting allows you to set a maximum time which a camera may be suspended for before it automatically resumes motion detection. This time can be extended by subsequent suspend indications after the first so continuous camera movement will also occur while the monitor is suspended.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 31, Name = 'ZM_OPT_REMOTE_CAMERAS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Are you going to use remote/networked cameras', Help = 'ZoneMinder can work with both local cameras, ie. those attached physically to your computer and remote or network cameras. If you will be using networked cameras select this option.', Category = 'hidden', Readonly = '0', Requires = ''; +insert into Config set Id = 32, Name = 'ZM_NETCAM_REGEXPS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use regular expression matching with network cameras', Help = 'Traditionally ZoneMinder has used complex regular regular expressions to handle the multitude of formats that network cameras produce. In versions from 1.21.1 the default is to use a simpler and faster built in pattern matching methodology. This works well with most networks cameras but if you have problems you can try the older, but more flexible, regular expression based method by selecting this option. Note, to use this method you must have libpcre installed on your system.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_REMOTE_CAMERAS=1'; +insert into Config set Id = 33, Name = 'ZM_HTTP_VERSION', Value = '1.1', Type = 'string', DefaultValue = '1.1', Hint = '1.1|1.0', Pattern = '(?^:^(1\.[01])$)', Format = ' $1?$1:\"\" ', Prompt = 'The version of HTTP that ZoneMinder will use to connect', Help = 'ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.', Category = 'network', Readonly = '0', Requires = ''; +insert into Config set Id = 34, Name = 'ZM_HTTP_UA', Value = 'ZoneMinder', Type = 'string', DefaultValue = 'ZoneMinder', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The user agent that ZoneMinder uses to identify itself', Help = 'When ZoneMinder communicates with remote cameras it will identify itself using this string and it\'s version number. This is normally sufficient, however if a particular cameras expects only to communicate with certain browsers then this can be changed to a different string identifying ZoneMinder as Internet Explorer or Netscape etc.', Category = 'network', Readonly = '0', Requires = ''; +insert into Config set Id = 35, Name = 'ZM_HTTP_TIMEOUT', Value = '2500', Type = 'integer', DefaultValue = '2500', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long ZoneMinder waits before giving up on images (milliseconds)', Help = 'When retrieving remote images ZoneMinder will wait for this length of time before deciding that an image is not going to arrive and taking steps to retry. This timeout is in milliseconds (1000 per second) and will apply to each part of an image if it is not sent in one whole chunk.', Category = 'network', Readonly = '0', Requires = ''; +insert into Config set Id = 36, Name = 'ZM_MIN_RTP_PORT', Value = '40200', Type = 'integer', DefaultValue = '40200', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Minimum port that ZoneMinder will listen for RTP traffic on', Help = 'When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the minimum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting.', Category = 'network', Readonly = '0', Requires = ''; +insert into Config set Id = 37, Name = 'ZM_MAX_RTP_PORT', Value = '40499', Type = 'integer', DefaultValue = '40499', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Maximum port that ZoneMinder will listen for RTP traffic on', Help = 'When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the maximum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting. You should also ensure that you have opened up at least two ports for each monitor that will be connecting to unicasting network cameras.', Category = 'network', Readonly = '0', Requires = ''; +insert into Config set Id = 38, Name = 'ZM_OPT_FFMPEG', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Is the ffmpeg video encoder/decoder installed', Help = 'ZoneMinder can optionally encode a series of video images into an MPEG encoded movie file for viewing, downloading or storage. This option allows you to specify whether you have the ffmpeg tools installed. Note that creating MPEG files can be fairly CPU and disk intensive and is not a required option as events can still be reviewed as video streams without it.', Category = 'images', Readonly = '0', Requires = ''; +insert into Config set Id = 39, Name = 'ZM_PATH_FFMPEG', Value = '/usr/bin/ffmpeg', Type = 'string', DefaultValue = '/usr/bin/ffmpeg', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to (optional) ffmpeg mpeg encoder', Help = 'This path should point to where ffmpeg has been installed.', Category = 'images', Readonly = '0', Requires = 'ZM_OPT_FFMPEG=1'; +insert into Config set Id = 40, Name = 'ZM_FFMPEG_INPUT_OPTIONS', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Additional input options to ffmpeg', Help = 'Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before the -i option). Check the ffmpeg documentation for a full list of options which may be used here.', Category = 'images', Readonly = '0', Requires = 'ZM_OPT_FFMPEG=1'; +insert into Config set Id = 41, Name = 'ZM_FFMPEG_OUTPUT_OPTIONS', Value = '-r 25', Type = 'string', DefaultValue = '-r 25', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Additional output options to ffmpeg', Help = 'Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after the -i option). Check the ffmpeg documentation for a full list of options which may be used here. The most common one will often be to force an output frame rate supported by the video encoder.', Category = 'images', Readonly = '0', Requires = 'ZM_OPT_FFMPEG=1'; +insert into Config set Id = 42, Name = 'ZM_FFMPEG_FORMATS', Value = 'mpg mpeg wmv asf avi* mov swf 3gp**', Type = 'string', DefaultValue = 'mpg mpeg wmv asf avi* mov swf 3gp**', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Formats to allow for ffmpeg video generation', Help = 'Ffmpeg can generate video in many different formats. This option allows you to list the ones you want to be able to select. As new formats are supported by ffmpeg you can add them here and be able to use them immediately. Adding a \'*\' after a format indicates that this will be the default format used for web video, adding \'**\' defines the default format for phone video.', Category = 'images', Readonly = '0', Requires = 'ZM_OPT_FFMPEG=1'; +insert into Config set Id = 43, Name = 'ZM_LOG_LEVEL_SYSLOG', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Save logging output to the system log', Help = 'ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 44, Name = 'ZM_LOG_LEVEL_FILE', Value = '-5', Type = 'integer', DefaultValue = '-5', Hint = 'None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Save logging output to component files', Help = 'ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 45, Name = 'ZM_LOG_LEVEL_WEBLOG', Value = '-5', Type = 'integer', DefaultValue = '-5', Hint = 'None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Save logging output to the weblog', Help = 'ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 46, Name = 'ZM_LOG_LEVEL_DATABASE', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Save logging output to the database', Help = 'ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 47, Name = 'ZM_LOG_DATABASE_LIMIT', Value = '7 day', Type = 'string', DefaultValue = '7 day', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Maximum number of log entries to retain', Help = 'If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as \' day\' which will limit the log entries to those newer than that time. You can specify \'hour\', \'day\', \'week\', \'month\' and \'year\', note that the values should be singular (no \'s\' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 48, Name = 'ZM_LOG_DEBUG', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Switch debugging on', Help = 'ZoneMinder components usually support debug logging available to help with diagnosing problems. Binary components have several levels of debug whereas more other components have only one. Normally this is disabled to minimise performance penalties and avoid filling logs too quickly. This option lets you switch on other options that allow you to configure additional debug information to be output. Components will pick up this instruction when they are restarted.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 49, Name = 'ZM_LOG_DEBUG_TARGET', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What components should have extra debug enabled', Help = 'There are three scopes of debug available. Leaving this option blank means that all components will use extra debug (not recommended). Setting this option to \'_\', e.g. _zmc, will limit extra debug to that component only. Setting this option to \'__\', e.g. \'_zmc_m1\' will limit extra debug to that instance of the component only. This is ordinarily what you probably want to do. To debug scripts use their names without the .pl extension, e.g. \'_zmvideo\' and to debug issues with the web interface use \'_web\'. You can specify multiple targets by separating them with \'|\' characters.', Category = 'logging', Readonly = '0', Requires = 'ZM_LOG_DEBUG=1'; +insert into Config set Id = 50, Name = 'ZM_LOG_DEBUG_LEVEL', Value = '1', Type = 'integer', DefaultValue = '1', Hint = '1|2|3|4|5|6|7|8|9', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What level of extra debug should be enabled', Help = 'There are 9 levels of debug available, with higher numbers being more debug and level 0 being no debug. However not all levels are used by all components. Also if there is debug at a high level it is usually likely to be output at such a volume that it may obstruct normal operation. For this reason you should set the level carefully and cautiously until the degree of debug you wish to see is present. Scripts and the web interface only have one level so this is an on/off type option for them.', Category = 'logging', Readonly = '0', Requires = 'ZM_LOG_DEBUG=1'; +insert into Config set Id = 51, Name = 'ZM_LOG_DEBUG_FILE', Value = '/tmp/zm/zm_debug.log+', Type = 'string', DefaultValue = '/tmp/zm/zm_debug.log+', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Where extra debug is output to', Help = 'This option allows you to specify a different target for debug output. All components have a default log file which will norally be in /tmp or /var/log and this is where debug will be written to if this value is empty. Adding a path here will temporarily redirect debug, and other logging output, to this file. This option is a simple filename and you are debugging several components then they will all try and write to the same file with undesirable consequences. Appending a \'+\' to the filename will cause the file to be created with a \'.\' suffix containing your process id. In this way debug from each run of a component is kept separate. This is the recommended setting as it will also prevent subsequent runs from overwriting the same log. You should ensure that permissions are set up to allow writing to the file and directory specified here.', Category = 'logging', Readonly = '0', Requires = 'ZM_LOG_DEBUG=1'; +insert into Config set Id = 52, Name = 'ZM_LOG_CHECK_PERIOD', Value = '900', Type = 'integer', DefaultValue = '900', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Time period used when calculating overall system health', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to indicate what period of historical events are used in this calculation. This value is expressed in seconds and is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 53, Name = 'ZM_LOG_ALERT_WAR_COUNT', Value = '1', Type = 'integer', DefaultValue = '1', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of warnings indicating system alert state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alert state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 54, Name = 'ZM_LOG_ALERT_ERR_COUNT', Value = '1', Type = 'integer', DefaultValue = '1', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of errors indicating system alert state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alert state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 55, Name = 'ZM_LOG_ALERT_FAT_COUNT', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of fatal error indicating system alert state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alert state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 56, Name = 'ZM_LOG_ALARM_WAR_COUNT', Value = '100', Type = 'integer', DefaultValue = '100', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of warnings indicating system alarm state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alarm state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 57, Name = 'ZM_LOG_ALARM_ERR_COUNT', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of errors indicating system alarm state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alarm state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 58, Name = 'ZM_LOG_ALARM_FAT_COUNT', Value = '1', Type = 'integer', DefaultValue = '1', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Number of fatal error indicating system alarm state', Help = 'When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alarm state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 59, Name = 'ZM_RECORD_EVENT_STATS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Record event statistical information, switch off if too slow', Help = 'This version of ZoneMinder records detailed information about events in the Stats table. This can help in profiling what the optimum settings are for Zones though this is tricky at present. However in future releases this will be done more easily and intuitively, especially with a large sample of events. The default option of \'yes\' allows this information to be collected now in readiness for this but if you are concerned about performance you can switch this off in which case no Stats information will be saved.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 60, Name = 'ZM_RECORD_DIAG_IMAGES', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Record intermediate alarm diagnostic images, can be very slow', Help = 'In addition to recording event statistics you can also record the intermediate diagnostic images that display the results of the various checks and processing that occur when trying to determine if an alarm event has taken place. There are several of these images generated for each frame and zone for each alarm or alert frame so this can have a massive impact on performance. Only switch this setting on for debug or analysis purposes and remember to switch it off again once no longer required.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 61, Name = 'ZM_DUMP_CORES', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Create core files on unexpected process failure.', Help = 'When an unrecoverable error occurs in a ZoneMinder binary process is has traditionally been trapped and the details written to logs to aid in remote analysis. However in some cases it is easier to diagnose the error if a core file, which is a memory dump of the process at the time of the error, is created. This can be interactively analysed in the debugger and may reveal more or better information than that available from the logs. This option is recommended for advanced users only otherwise leave at the default. Note using this option to trigger core files will mean that there will be no indication in the binary logs that a process has died, they will just stop, however the zmdc log will still contain an entry. Also note that you may have to explicitly enable core file creation on your system via the \'ulimit -c\' command or other means otherwise no file will be created regardless of the value of this option.', Category = 'logging', Readonly = '0', Requires = ''; +insert into Config set Id = 62, Name = 'ZM_PATH_MAP', Value = '/dev/shm', Type = 'string', DefaultValue = '/dev/shm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to the mapped memory files that that ZoneMinder can use', Help = 'ZoneMinder has historically used IPC shared memory for shared data between processes. This has it\'s advantages and limitations. This version of ZoneMinder can use an alternate method, mapped memory, instead with can be enabled with the --enable--mmap directive to configure. This requires less system configuration and is generally more flexible. However it requires each shared data segment to map onto a filesystem file. This option indicates where those mapped files go. You should ensure that this location has sufficient space for these files and for the best performance it should be a tmpfs file system or ramdisk otherwise disk access may render this method slower than the regular shared memory one.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 63, Name = 'ZM_PATH_SOCKS', Value = '/tmp/zm', Type = 'string', DefaultValue = '/tmp/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to the various Unix domain socket files that ZoneMinder uses', Help = 'ZoneMinder generally uses Unix domain sockets where possible. This reduces the need for port assignments and prevents external applications from possibly compromising the daemons. However each Unix socket requires a .sock file to be created. This option indicates where those socket files go.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 64, Name = 'ZM_PATH_LOGS', Value = '/var/log/zm', Type = 'string', DefaultValue = '/var/log/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to the various logs that the ZoneMinder daemons generate', Help = 'There are various daemons that are used by ZoneMinder to perform various tasks. Most generate helpful log files and this is where they go. They can be deleted if not required for debugging.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 65, Name = 'ZM_PATH_SWAP', Value = '/tmp/zm', Type = 'string', DefaultValue = '/tmp/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to location for temporary swap images used in streaming', Help = 'Buffered playback requires temporary swap images to be stored for each instance of the streaming daemons. This option determines where these images will be stored. The images will actually be stored in sub directories beneath this location and will be automatically cleaned up after a period of time.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 66, Name = 'ZM_WEB_TITLE_PREFIX', Value = 'ZM', Type = 'string', DefaultValue = 'ZM', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The title prefix displayed on each window', Help = 'If you have more than one installation of ZoneMinder it can be helpful to display different titles for each one. Changing this option allows you to customise the window titles to include further information to aid identification.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 67, Name = 'ZM_WEB_RESIZE_CONSOLE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should the console window resize itself to fit', Help = 'Traditionally the main ZoneMinder web console window has resized itself to shrink to a size small enough to list only the monitors that are actually present. This is intended to make the window more unobtrusize but may not be to everyones tastes, especially if opened in a tab in browsers which support this kind if layout. Switch this option off to have the console window size left to the users preference', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 68, Name = 'ZM_WEB_POPUP_ON_ALARM', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should the monitor window jump to the top if an alarm occurs', Help = 'When viewing a live monitor stream you can specify whether you want the window to pop to the front if an alarm occurs when the window is minimised or behind another window. This is most useful if your monitors are over doors for example when they can pop up if someone comes to the doorway.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 69, Name = 'ZM_OPT_X10', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Support interfacing with X10 devices', Help = 'If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.', Category = 'x10', Readonly = '0', Requires = ''; +insert into Config set Id = 70, Name = 'ZM_X10_DEVICE', Value = '/dev/ttyS0', Type = 'string', DefaultValue = '/dev/ttyS0', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'What device is your X10 controller connected on', Help = 'If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.', Category = 'x10', Readonly = '0', Requires = 'ZM_OPT_X10=1'; +insert into Config set Id = 71, Name = 'ZM_X10_HOUSE_CODE', Value = 'A', Type = 'string', DefaultValue = 'A', Hint = 'A-P', Pattern = '(?^i:^([A-P]))', Format = ' uc($1) ', Prompt = 'What X10 house code should be used', Help = 'X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.', Category = 'x10', Readonly = '0', Requires = 'ZM_OPT_X10=1'; +insert into Config set Id = 72, Name = 'ZM_X10_DB_RELOAD_INTERVAL', Value = '60', Type = 'integer', DefaultValue = '60', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the X10 daemon reloads the monitors from the database', Help = 'The zmx10 daemon periodically checks the database to find out what X10 events trigger, or result from, alarms. This option determines how frequently this check occurs, unless you change this area frequently this can be a fairly large value.', Category = 'x10', Readonly = '0', Requires = 'ZM_OPT_X10=1'; +insert into Config set Id = 73, Name = 'ZM_WEB_SOUND_ON_ALARM', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should the monitor window play a sound if an alarm occurs', Help = 'When viewing a live monitor stream you can specify whether you want the window to play a sound to alert you if an alarm occurs.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 74, Name = 'ZM_WEB_ALARM_SOUND', Value = '', Type = 'string', DefaultValue = '', Hint = 'filename', Pattern = '(?^:^([a-zA-Z0-9-_.]+)$)', Format = ' $1 ', Prompt = 'The sound to play on alarm, put this in the sounds directory', Help = 'You can specify a sound file to play if an alarm occurs whilst you are watching a live monitor stream. So long as your browser understands the format it does not need to be any particular type. This file should be placed in the sounds directory defined earlier.', Category = 'web', Readonly = '0', Requires = 'ZM_WEB_SOUND_ON_ALARM=1'; +insert into Config set Id = 75, Name = 'ZM_WEB_COMPACT_MONTAGE', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Compact the montage view by removing extra detail', Help = 'The montage view shows the output of all of your active monitors in one window. This include a small menu and status information for each one. This can increase the web traffic and make the window larger than may be desired. Setting this option on removes all this extraneous information and just displays the images.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 76, Name = 'ZM_OPT_FAST_DELETE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Delete only event database records for speed', Help = 'Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if your are trying to do a lot of events at once. It is recommended that you set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 77, Name = 'ZM_STRICT_VIDEO_CONFIG', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Allow errors in setting video config to be fatal', Help = 'With some video devices errors can be reported in setting the various video attributes when in fact the operation was successful. Switching this option off will still allow these errors to be reported but will not cause them to kill the video capture daemon. Note however that doing this will cause all errors to be ignored including those which are genuine and which may cause the video capture to not function correctly. Use this option with caution.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 78, Name = 'ZM_SIGNAL_CHECK_POINTS', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How many points in a captured image to check for signal loss', Help = 'For locally attached video cameras ZoneMinder can check for signal loss by looking at a number of random points on each captured image. If all of these points are set to the same fixed colour then the camera is assumed to have lost signal. When this happens any open events are closed and a short one frame signal loss event is generated, as is another when the signal returns. This option defines how many points on each image to check. Note that this is a maximum, any points found to not have the check colour will abort any further checks so in most cases on a couple of points will actually be checked. Network and file based cameras are never checked.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 79, Name = 'ZM_V4L_MULTI_BUFFER', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use more than one buffer for Video 4 Linux devices', Help = 'Performance when using Video 4 Linux devices is usually best if multiple buffers are used allowing the next image to be captured while the previous one is being processed. If you have multiple devices on a card sharing one input that requires switching then this approach can sometimes cause frames from one source to be mixed up with frames from another. Switching this option off prevents multi buffering resulting in slower but more stable image capture. This option is ignored for non-local cameras or if only one input is present on a capture chip. This option addresses a similar problem to the ZM_CAPTURES_PER_FRAME option and you should normally change the value of only one of the options at a time.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 80, Name = 'ZM_CAPTURES_PER_FRAME', Value = '1', Type = 'integer', DefaultValue = '1', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How many images are captured per returned frame, for shared local cameras', Help = 'If you are using cameras attached to a video capture card which forces multiple inputs to share one capture chip, it can sometimes produce images with interlaced frames reversed resulting in poor image quality and a distinctive comb edge appearance. Increasing this setting allows you to force additional image captures before one is selected as the captured frame. This allows the capture hardware to \'settle down\' and produce better quality images at the price of lesser capture rates. This option has no effect on (a) network cameras, or (b) where multiple inputs do not share a capture chip. This option addresses a similar problem to the ZM_V4L_MULTI_BUFFER option and you should normally change the value of only one of the options at a time.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 81, Name = 'ZM_FILTER_RELOAD_DELAY', Value = '300', Type = 'integer', DefaultValue = '300', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) filters are reloaded in zmfilter', Help = 'ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are reloaded from the database to get the latest versions or new filters. If you don\'t change filters very often this value can be set to a large value.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 82, Name = 'ZM_FILTER_EXECUTE_INTERVAL', Value = '60', Type = 'integer', DefaultValue = '60', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) to run automatic saved filters', Help = 'ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are executed on the saved event in the database. If you want a rapid response to new events this should be a smaller value, however this may increase the overall load on the system and affect performance of other elements.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 83, Name = 'ZM_OPT_UPLOAD', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should ZoneMinder support uploading events from filters', Help = 'In ZoneMinder you can create event filters that specify whether events that match certain criteria should be uploaded to a remote server for archiving. This option specifies whether this functionality should be available', Category = 'upload', Readonly = '0', Requires = ''; +insert into Config set Id = 84, Name = 'ZM_UPLOAD_ARCH_FORMAT', Value = 'tar', Type = 'string', DefaultValue = 'tar', Hint = 'tar|zip', Pattern = '(?^i:^([tz]))', Format = ' $1 =~ /^t/ ? \"tar\" : \"zip\" ', Prompt = 'What format the uploaded events should be created in.', Help = 'Uploaded events may be stored in either .tar or .zip format, this option specifies which. Note that to use this you will need to have the Archive::Tar and/or Archive::Zip perl modules installed.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 85, Name = 'ZM_UPLOAD_ARCH_COMPRESS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should archive files be compressed', Help = 'When the archive files are created they can be compressed. However in general since the images are compressed already this saves only a minimal amount of space versus utilising more CPU in their creation. Only enable if you have CPU to waste and are limited in disk space on your remote server or bandwidth.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 86, Name = 'ZM_UPLOAD_ARCH_ANALYSE', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Include the analysis files in the archive', Help = 'When the archive files are created they can contain either just the captured frames or both the captured frames and, for frames that caused an alarm, the analysed image with the changed area highlighted. This option controls files are included. Only include analysed frames if you have a high bandwidth connection to the remote server or if you need help in figuring out what caused an alarm in the first place as archives with these files in can be considerably larger.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 87, Name = 'ZM_UPLOAD_PROTOCOL', Value = 'ftp', Type = 'string', DefaultValue = 'ftp', Hint = 'ftp|sftp', Pattern = '(?^i:^([tz]))', Format = ' $1 =~ /^f/ ? \"ftp\" : \"sftp\" ', Prompt = 'What protocol to use to upload events', Help = 'ZoneMinder can upload events to a remote server using either FTP or SFTP. Regular FTP is widely supported but not necessarily very secure whereas SFTP (Secure FTP) runs over an ssh connection and so is encrypted and uses regular ssh ports. Note that to use this you will need to have the appropriate perl module, either Net::FTP or Net::SFTP installed depending on your choice.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 88, Name = 'ZM_UPLOAD_FTP_HOST', Value = '', Type = 'string', DefaultValue = '', Hint = 'host.your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)$)', Format = ' $1 ', Prompt = 'The remote server to upload to', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the name, or ip address, of the server to use.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 89, Name = 'ZM_UPLOAD_HOST', Value = '', Type = 'string', DefaultValue = '', Hint = 'host.your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)$)', Format = ' $1 ', Prompt = 'The remote server to upload events to', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the name, or ip address, of the server to use.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 90, Name = 'ZM_UPLOAD_PORT', Value = '', Type = 'integer', DefaultValue = '', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'The port on the remote upload server, if not the default (SFTP only)', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. If you are using the SFTP protocol then this option allows you to specify a particular port to use for connection. If this option is left blank then the default, port 22, is used. This option is ignored for FTP uploads.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 91, Name = 'ZM_UPLOAD_FTP_USER', Value = '', Type = 'string', DefaultValue = '', Hint = 'alphanumeric', Pattern = '(?^:^([a-zA-Z0-9-_]+)$)', Format = ' $1 ', Prompt = 'Your ftp username', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the username that ZoneMinder should use to log in for ftp transfer.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 92, Name = 'ZM_UPLOAD_USER', Value = '', Type = 'string', DefaultValue = '', Hint = 'alphanumeric', Pattern = '(?^:^([a-zA-Z0-9-_]+)$)', Format = ' $1 ', Prompt = 'Remote server username', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 93, Name = 'ZM_UPLOAD_FTP_PASS', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Your ftp password', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the password that ZoneMinder should use to log in for ftp transfer.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 94, Name = 'ZM_UPLOAD_PASS', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Remote server password', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 95, Name = 'ZM_UPLOAD_FTP_LOC_DIR', Value = '/tmp/zm', Type = 'string', DefaultValue = '/tmp/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'The local directory in which to create upload files', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 96, Name = 'ZM_UPLOAD_LOC_DIR', Value = '/tmp/zm', Type = 'string', DefaultValue = '/tmp/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'The local directory in which to create upload files', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 97, Name = 'ZM_UPLOAD_FTP_REM_DIR', Value = '', Type = 'string', DefaultValue = '', Hint = 'relative/path/to/somewhere', Pattern = '(?^:^((?:[^/].*)?)/?$)', Format = ' $1 ', Prompt = 'The remote directory to upload to', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the remote directory that ZoneMinder should use to upload event files to.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 98, Name = 'ZM_UPLOAD_REM_DIR', Value = '', Type = 'string', DefaultValue = '', Hint = 'relative/path/to/somewhere', Pattern = '(?^:^((?:[^/].*)?)/?$)', Format = ' $1 ', Prompt = 'The remote directory to upload to', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the remote directory that ZoneMinder should use to upload event files to.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 99, Name = 'ZM_UPLOAD_FTP_TIMEOUT', Value = '120', Type = 'integer', DefaultValue = '120', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to allow the transfer to take for each file', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the maximum ftp inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 100, Name = 'ZM_UPLOAD_TIMEOUT', Value = '120', Type = 'integer', DefaultValue = '120', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to allow the transfer to take for each file', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the maximum inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 101, Name = 'ZM_UPLOAD_FTP_PASSIVE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use passive ftp when uploading', Help = 'If your computer is behind a firewall or proxy you may need to set FTP to passive mode. In fact for simple transfers it makes little sense to do otherwise anyway but you can set this to \'No\' if you wish.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 102, Name = 'ZM_UPLOAD_FTP_DEBUG', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Switch ftp debugging on', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote ftp server. If you are having (or expecting) troubles with uploading events then setting this to \'yes\' permits additional information to be included in the zmfilter log file.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 103, Name = 'ZM_UPLOAD_DEBUG', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Switch upload debugging on', Help = 'You can use filters to instruct ZoneMinder to upload events to a remote server. If you are having (or expecting) troubles with uploading events then setting this to \'yes\' permits additional information to be generated by the underlying transfer modules and included in the logs.', Category = 'upload', Readonly = '0', Requires = 'ZM_OPT_UPLOAD=1'; +insert into Config set Id = 104, Name = 'ZM_OPT_EMAIL', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should ZoneMinder email you details of events that match corresponding filters', Help = 'In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details emailed to you at a designated email address. This will allow you to be notified of events as soon as they occur and also to quickly view the events directly. This option specifies whether this functionality should be available. The email created with this option can be any size and is intended to be sent to a regular email reader rather than a mobile device.', Category = 'mail', Readonly = '0', Requires = ''; +insert into Config set Id = 105, Name = 'ZM_EMAIL_ADDRESS', Value = '', Type = 'string', DefaultValue = '', Hint = 'your.name@your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$)', Format = ' $1\@$2 ', Prompt = 'The email address to send matching event details to', Help = 'This option is used to define the email address that any events that match the appropriate filters will be sent to.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'; +insert into Config set Id = 106, Name = 'ZM_EMAIL_TEXT', Value = 'subject = \"ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)\" +body = \" +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder\"', Type = 'text', DefaultValue = 'subject = \"ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)\" +body = \" +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder\"', Hint = 'free text', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The text of the email used to send matching event details', Help = 'This option is used to define the content of the email that is sent for any events that match the appropriate filters.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'; +insert into Config set Id = 107, Name = 'ZM_EMAIL_SUBJECT', Value = 'ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The subject of the email used to send matching event details', Help = 'This option is used to define the subject of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'; +insert into Config set Id = 108, Name = 'ZM_EMAIL_BODY', Value = ' +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder', Type = 'text', DefaultValue = ' +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder', Hint = 'free text', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The body of the email used to send matching event details', Help = 'This option is used to define the content of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'; +insert into Config set Id = 109, Name = 'ZM_OPT_MESSAGE', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should ZoneMinder message you with details of events that match corresponding filters', Help = 'In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details sent to you at a designated short message email address. This will allow you to be notified of events as soon as they occur. This option specifies whether this functionality should be available. The email created by this option will be brief and is intended to be sent to an SMS gateway or a minimal mail reader such as a mobile device or phone rather than a regular email reader.', Category = 'mail', Readonly = '0', Requires = ''; +insert into Config set Id = 110, Name = 'ZM_MESSAGE_ADDRESS', Value = '', Type = 'string', DefaultValue = '', Hint = 'your.name@your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$)', Format = ' $1\@$2 ', Prompt = 'The email address to send matching event details to', Help = 'This option is used to define the short message email address that any events that match the appropriate filters will be sent to.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'; +insert into Config set Id = 111, Name = 'ZM_MESSAGE_TEXT', Value = 'subject = \"ZoneMinder: Alarm - %MN%-%EI%\" +body = \"ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.\"', Type = 'text', DefaultValue = 'subject = \"ZoneMinder: Alarm - %MN%-%EI%\" +body = \"ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.\"', Hint = 'free text', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The text of the message used to send matching event details', Help = 'This option is used to define the content of the message that is sent for any events that match the appropriate filters.', Category = 'hidden', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'; +insert into Config set Id = 112, Name = 'ZM_MESSAGE_SUBJECT', Value = 'ZoneMinder: Alarm - %MN%-%EI%', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI%', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The subject of the message used to send matching event details', Help = 'This option is used to define the subject of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'; +insert into Config set Id = 113, Name = 'ZM_MESSAGE_BODY', Value = 'ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.', Type = 'text', DefaultValue = 'ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.', Hint = 'free text', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The body of the message used to send matching event details', Help = 'This option is used to define the content of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'; +insert into Config set Id = 114, Name = 'ZM_NEW_MAIL_MODULES', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use a newer perl method to send emails', Help = 'Traditionally ZoneMinder has used the MIME::Entity perl module to construct and send notification emails and messages. Some people have reported problems with this module not being present at all or flexible enough for their needs. If you are one of those people this option allows you to select a new mailing method using MIME::Lite and Net::SMTP instead. This method was contributed by Ross Melin and should work for everyone but has not been extensively tested so currently is not selected by default.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1;ZM_OPT_MESSAGE=1'; +insert into Config set Id = 115, Name = 'ZM_EMAIL_HOST', Value = 'localhost', Type = 'string', DefaultValue = 'localhost', Hint = 'host.your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)$)', Format = ' $1 ', Prompt = 'The host address of your SMTP mail server', Help = 'If you have chosen SMTP as the method by which to send notification emails or messages then this option allows you to choose which SMTP server to use to send them. The default of localhost may work if you have the sendmail, exim or a similar daemon running however you may wish to enter your ISP\'s SMTP mail server here.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1;ZM_OPT_MESSAGE=1'; +insert into Config set Id = 116, Name = 'ZM_FROM_EMAIL', Value = '', Type = 'string', DefaultValue = '', Hint = 'your.name@your.domain', Pattern = '(?^:^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$)', Format = ' $1\@$2 ', Prompt = 'The email address you wish your event notifications to originate from', Help = 'The emails or messages that will be sent to you informing you of events can appear to come from a designated email address to help you with mail filtering etc. An address of something like ZoneMinder@your.domain is recommended.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1;ZM_OPT_MESSAGE=1'; +insert into Config set Id = 117, Name = 'ZM_URL', Value = '', Type = 'string', DefaultValue = '', Hint = 'http://host.your.domain/', Pattern = '(?^:^(?:http://)?(.+)$)', Format = ' \"http://\".$1 ', Prompt = 'The URL of your ZoneMinder installation', Help = 'The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. http://host.your.domain/zm.php.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1;ZM_OPT_MESSAGE=1'; +insert into Config set Id = 118, Name = 'ZM_MAX_RESTART_DELAY', Value = '600', Type = 'integer', DefaultValue = '600', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Maximum delay (in seconds) for daemon restart attempts.', Help = 'The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 119, Name = 'ZM_WATCH_CHECK_INTERVAL', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often to check the capture daemons have not locked up', Help = 'The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 120, Name = 'ZM_WATCH_MAX_DELAY', Value = '5', Type = 'decimal', DefaultValue = '5', Hint = 'decimal', Pattern = '(?^:^(\d+(?:\.\d+)?)$)', Format = ' $1 ', Prompt = 'The maximum delay allowed since the last captured image', Help = 'The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 121, Name = 'ZM_RUN_AUDIT', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Run zmaudit to check data consistency', Help = 'The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using \'fast deletes\' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 122, Name = 'ZM_AUDIT_CHECK_INTERVAL', Value = '900', Type = 'integer', DefaultValue = '900', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often to check database and filesystem consistency', Help = 'The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using \'fast deletes\' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 123, Name = 'ZM_FORCED_ALARM_SCORE', Value = '255', Type = 'integer', DefaultValue = '255', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Score to give forced alarms', Help = 'The \'zmu\' utility can be used to force an alarm on a monitor rather than rely on the motion detection algorithms. This option determines what score to give these alarms to distinguish them from regular ones. It must be 255 or less.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 124, Name = 'ZM_BULK_FRAME_INTERVAL', Value = '100', Type = 'integer', DefaultValue = '100', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often a bulk frame should be written to the database', Help = 'Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation (\'Record\' or \'Mocord\' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one \'bulk\' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 125, Name = 'ZM_EVENT_CLOSE_MODE', Value = 'idle', Type = 'string', DefaultValue = 'idle', Hint = 'time|idle|alarm', Pattern = '(?^i:^([tia]))', Format = ' ($1 =~ /^t/) ? \"time\" : ($1 =~ /^i/ ? \"idle\" : \"time\" ) ', Prompt = 'When continuous events are closed.', Help = 'When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The \'time\' setting means that the event will be closed at the end of the section regardless of alarm activity. The \'idle\' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The \'alarm\' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 126, Name = 'ZM_FORCE_CLOSE_EVENTS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Close events at section ends.', Help = 'When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section and ordinarily this will prevent the event being closed until the motion has ceased. Switching this option on will force the event closed at the specified time regardless of any motion activity.', Category = 'hidden', Readonly = '0', Requires = ''; +insert into Config set Id = 127, Name = 'ZM_CREATE_ANALYSIS_IMAGES', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Create analysed alarm images with motion outlined', Help = 'By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 128, Name = 'ZM_WEIGHTED_ALARM_CENTRES', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Use a weighted algorithm to calculate the centre of an alarm', Help = 'ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 129, Name = 'ZM_EVENT_IMAGE_DIGITS', Value = '3', Type = 'integer', DefaultValue = '3', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How many significant digits are used in event image numbering', Help = 'As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 130, Name = 'ZM_DEFAULT_ASPECT_RATIO', Value = '4:3', Type = 'string', DefaultValue = '4:3', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'The default width:height aspect ratio used in monitors', Help = 'When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format : and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 131, Name = 'ZM_USER_SELF_EDIT', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Allow unprivileged users to change their details', Help = 'Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 132, Name = 'ZM_OPT_FRAME_SERVER', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Should analysis farm out the writing of images to disk', Help = 'In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 133, Name = 'ZM_FRAME_SOCKET_SIZE', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'Specify the frame server socket buffer size if non-standard', Help = 'For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option', Category = 'system', Readonly = '0', Requires = 'ZM_OPT_FRAME_SERVER=1'; +insert into Config set Id = 134, Name = 'ZM_OPT_CONTROL', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Support controllable (e.g. PTZ) cameras', Help = 'ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 135, Name = 'ZM_OPT_TRIGGERS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Interface external event triggers via socket or device files', Help = 'ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 136, Name = 'ZM_CHECK_FOR_UPDATES', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Check with zoneminder.com for updated versions', Help = 'From ZoneMinder version 1.17.0 onwards new versions are expected to be more frequent. To save checking manually for each new version ZoneMinder can check with the zoneminder.com website to determine the most recent release. These checks are infrequent, about once per week, and no personal or system information is transmitted other than your current version number. If you do not wish these checks to take place or your ZoneMinder system has no internet access you can switch these check off with this configuration variable', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 137, Name = 'ZM_UPDATE_CHECK_PROXY', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Proxy url if required to access zoneminder.com', Help = 'If you use a proxy to access the internet then ZoneMinder needs to know so it can access zoneminder.com to check for updates. If you do use a proxy enter the full proxy url here in the form of http://:/', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 138, Name = 'ZM_SHM_KEY', Value = '0x7a6d0000', Type = 'hexadecimal', DefaultValue = '0x7a6d0000', Hint = 'hexadecimal', Pattern = '(?^:^(?:0x)?([0-9a-f]{1,8})$)', Format = ' \"0x\".$1 ', Prompt = 'Shared memory root key to use', Help = 'ZoneMinder uses shared memory to speed up communication between modules. To identify the right area to use shared memory keys are used. This option controls what the base key is, each monitor will have it\'s Id or\'ed with this to get the actual key used. You will not normally need to change this value unless it clashes with another instance of ZoneMinder on the same machine. Only the first four hex digits are used, the lower four will be masked out and ignored.', Category = 'system', Readonly = '0', Requires = ''; +insert into Config set Id = 139, Name = 'ZM_WEB_REFRESH_METHOD', Value = 'javascript', Type = 'string', DefaultValue = 'javascript', Hint = 'javascript|http', Pattern = '(?^i:^([jh]))', Format = ' $1 =~ /^j/ ? \"javascript\" : \"http\" ', Prompt = 'What method windows should use to refresh themselves', Help = 'Many windows in Javascript need to refresh themselves to keep their information current. This option determines what method they should use to do this. Choosing \'javascript\' means that each window will have a short JavaScript statement in with a timer to prompt the refresh. This is the most compatible method. Choosing \'http\' means the refresh instruction is put in the HTTP header. This is a cleaner method but refreshes are interrupted or cancelled when a link in the window is clicked meaning that the window will no longer refresh and this would have to be done manually.', Category = 'hidden', Readonly = '0', Requires = ''; +insert into Config set Id = 140, Name = 'ZM_WEB_EVENT_SORT_FIELD', Value = 'DateTime', Type = 'string', DefaultValue = 'DateTime', Hint = 'Id|Name|Cause|MonitorName|DateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore', Pattern = '(?^:.)', Format = ' $1 ', Prompt = 'Default field the event lists are sorted by', Help = 'Events in lists can be initially ordered in any way you want. This option controls what field is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the \'Prev\' and \'Next\' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 141, Name = 'ZM_WEB_EVENT_SORT_ORDER', Value = 'asc', Type = 'string', DefaultValue = 'asc', Hint = 'asc|desc', Pattern = '(?^i:^([ad]))', Format = ' $1 =~ /^a/i ? \"asc\" : \"desc\" ', Prompt = 'Default order the event lists are sorted by', Help = 'Events in lists can be initially ordered in any way you want. This option controls what order (ascending or descending) is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the \'Prev\' and \'Next\' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 142, Name = 'ZM_WEB_EVENTS_PER_PAGE', Value = '25', Type = 'integer', DefaultValue = '25', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How many events to list per page in paged mode', Help = 'In the event list view you can either list all events or just a page at a time. This option controls how many events are listed per page in paged mode and how often to repeat the column headers in non-paged mode.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 143, Name = 'ZM_WEB_LIST_THUMBS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Display mini-thumbnails of event images in event lists', Help = 'Ordinarily the event lists just display text details of the events to save space and time. By switching this option on you can also display small thumbnails to help you identify events of interest. The size of these thumbnails is controlled by the following two options.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 144, Name = 'ZM_WEB_LIST_THUMB_WIDTH', Value = '48', Type = 'integer', DefaultValue = '48', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'The width of the thumbnails that appear in the event lists', Help = 'This options controls the width of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a height instead in the next option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.', Category = 'web', Readonly = '0', Requires = 'ZM_WEB_LIST_THUMBS=1'; +insert into Config set Id = 145, Name = 'ZM_WEB_LIST_THUMB_HEIGHT', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'The height of the thumbnails that appear in the event lists', Help = 'This options controls the height of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a width instead in the previous option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.', Category = 'web', Readonly = '0', Requires = 'ZM_WEB_LIST_THUMBS=1'; +insert into Config set Id = 146, Name = 'ZM_WEB_USE_OBJECT_TAGS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Wrap embed in object tags for media content', Help = 'There are two methods of including media content in web pages. The most common way is use the EMBED tag which is able to give some indication of the type of content. However this is not a standard part of HTML. The official method is to use OBJECT tags which are able to give more information allowing the correct media viewers etc to be loaded. However these are less widely supported and content may be specifically tailored to a particular platform or player. This option controls whether media content is enclosed in EMBED tags only or whether, where appropriate, it is additionally wrapped in OBJECT tags. Currently OBJECT tags are only used in a limited number of circumstances but they may become more widespread in the future. It is suggested that you leave this option on unless you encounter problems playing some content.', Category = 'web', Readonly = '0', Requires = ''; +insert into Config set Id = 147, Name = 'ZM_WEB_H_REFRESH_MAIN', Value = '300', Type = 'integer', DefaultValue = '300', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the main console window should refresh itself', Help = 'The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 148, Name = 'ZM_WEB_H_REFRESH_CYCLE', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the cycle watch window swaps to the next monitor', Help = 'The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 149, Name = 'ZM_WEB_H_REFRESH_IMAGE', Value = '5', Type = 'integer', DefaultValue = '5', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the watched image is refreshed (if not streaming)', Help = 'The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 150, Name = 'ZM_WEB_H_REFRESH_STATUS', Value = '3', Type = 'integer', DefaultValue = '3', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the status refreshes itself in the watch window', Help = 'The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 151, Name = 'ZM_WEB_H_REFRESH_EVENTS', Value = '30', Type = 'integer', DefaultValue = '30', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the event listing is refreshed in the watch window', Help = 'The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 152, Name = 'ZM_WEB_H_CAN_STREAM', Value = 'auto', Type = 'string', DefaultValue = 'auto', Hint = 'auto|yes|no', Pattern = '(?^i:^([ayn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : ($1 =~ /^n/ ? \"no\" : \"auto\" ) ', Prompt = 'Override the automatic detection of browser streaming capability', Help = 'If you know that your browser can handle image streams of the type \'multipart/x-mixed-replace\' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting \'yes\' will tell ZoneMinder that your browser can handle the streams natively, \'no\' means that it can\'t and so the plugin will be used while \'auto\' lets ZoneMinder decide.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 153, Name = 'ZM_WEB_H_STREAM_METHOD', Value = 'jpeg', Type = 'string', DefaultValue = 'jpeg', Hint = 'mpeg|jpeg', Pattern = '(?^i:^([mj]))', Format = ' $1 =~ /^m/ ? \"mpeg\" : \"jpeg\" ', Prompt = 'Which method should be used to send video streams to your browser.', Help = 'ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 154, Name = 'ZM_WEB_H_DEFAULT_SCALE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|33|50|75|100|150|200|300|400', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'live\' or \'event\' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 155, Name = 'ZM_WEB_H_DEFAULT_RATE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|50|100|150|200|400|1000|2500|5000|10000', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default replay rate factor applied to \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'event\' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 156, Name = 'ZM_WEB_H_VIDEO_BITRATE', Value = '150000', Type = 'integer', DefaultValue = '150000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the bitrate of the video encoded stream should be set to', Help = 'When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a \'quality\' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 157, Name = 'ZM_WEB_H_VIDEO_MAXFPS', Value = '15', Type = 'integer', DefaultValue = '15', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the maximum frame rate for streamed video should be', Help = 'When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 158, Name = 'ZM_WEB_H_SCALE_THUMBS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Scale thumbnails in events, bandwidth versus cpu in rescaling', Help = 'If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 159, Name = 'ZM_WEB_H_EVENTS_VIEW', Value = 'events', Type = 'string', DefaultValue = 'events', Hint = 'events|timeline', Pattern = '(?^i:^([lt]))', Format = ' $1 =~ /^e/ ? \"events\" : \"timeline\" ', Prompt = 'What the default view of multiple events should be.', Help = 'Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 160, Name = 'ZM_WEB_H_SHOW_PROGRESS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Show the progress of replay in event view.', Help = 'When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 161, Name = 'ZM_WEB_H_AJAX_TIMEOUT', Value = '3000', Type = 'integer', DefaultValue = '3000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to wait for Ajax request responses (ms)', Help = 'The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.', Category = 'highband', Readonly = '0', Requires = ''; +insert into Config set Id = 162, Name = 'ZM_WEB_M_REFRESH_MAIN', Value = '300', Type = 'integer', DefaultValue = '300', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the main console window should refresh itself', Help = 'The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 163, Name = 'ZM_WEB_M_REFRESH_CYCLE', Value = '20', Type = 'integer', DefaultValue = '20', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the cycle watch window swaps to the next monitor', Help = 'The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 164, Name = 'ZM_WEB_M_REFRESH_IMAGE', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the watched image is refreshed (if not streaming)', Help = 'The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 165, Name = 'ZM_WEB_M_REFRESH_STATUS', Value = '5', Type = 'integer', DefaultValue = '5', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the status refreshes itself in the watch window', Help = 'The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 166, Name = 'ZM_WEB_M_REFRESH_EVENTS', Value = '60', Type = 'integer', DefaultValue = '60', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the event listing is refreshed in the watch window', Help = 'The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 167, Name = 'ZM_WEB_M_CAN_STREAM', Value = 'auto', Type = 'string', DefaultValue = 'auto', Hint = 'auto|yes|no', Pattern = '(?^i:^([ayn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : ($1 =~ /^n/ ? \"no\" : \"auto\" ) ', Prompt = 'Override the automatic detection of browser streaming capability', Help = 'If you know that your browser can handle image streams of the type \'multipart/x-mixed-replace\' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting \'yes\' will tell ZoneMinder that your browser can handle the streams natively, \'no\' means that it can\'t and so the plugin will be used while \'auto\' lets ZoneMinder decide.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 168, Name = 'ZM_WEB_M_STREAM_METHOD', Value = 'jpeg', Type = 'string', DefaultValue = 'jpeg', Hint = 'mpeg|jpeg', Pattern = '(?^i:^([mj]))', Format = ' $1 =~ /^m/ ? \"mpeg\" : \"jpeg\" ', Prompt = 'Which method should be used to send video streams to your browser.', Help = 'ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 169, Name = 'ZM_WEB_M_DEFAULT_SCALE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|33|50|75|100|150|200|300|400', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'live\' or \'event\' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 170, Name = 'ZM_WEB_M_DEFAULT_RATE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|50|100|150|200|400|1000|2500|5000|10000', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default replay rate factor applied to \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'event\' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 171, Name = 'ZM_WEB_M_VIDEO_BITRATE', Value = '75000', Type = 'integer', DefaultValue = '75000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the bitrate of the video encoded stream should be set to', Help = 'When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a \'quality\' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 172, Name = 'ZM_WEB_M_VIDEO_MAXFPS', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the maximum frame rate for streamed video should be', Help = 'When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 173, Name = 'ZM_WEB_M_SCALE_THUMBS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Scale thumbnails in events, bandwidth versus cpu in rescaling', Help = 'If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 174, Name = 'ZM_WEB_M_EVENTS_VIEW', Value = 'events', Type = 'string', DefaultValue = 'events', Hint = 'events|timeline', Pattern = '(?^i:^([lt]))', Format = ' $1 =~ /^e/ ? \"events\" : \"timeline\" ', Prompt = 'What the default view of multiple events should be.', Help = 'Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 175, Name = 'ZM_WEB_M_SHOW_PROGRESS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Show the progress of replay in event view.', Help = 'When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 176, Name = 'ZM_WEB_M_AJAX_TIMEOUT', Value = '5000', Type = 'integer', DefaultValue = '5000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to wait for Ajax request responses (ms)', Help = 'The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.', Category = 'medband', Readonly = '0', Requires = ''; +insert into Config set Id = 177, Name = 'ZM_WEB_L_REFRESH_MAIN', Value = '300', Type = 'integer', DefaultValue = '300', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the main console window should refresh itself', Help = 'The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 178, Name = 'ZM_WEB_L_REFRESH_CYCLE', Value = '30', Type = 'integer', DefaultValue = '30', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the cycle watch window swaps to the next monitor', Help = 'The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 179, Name = 'ZM_WEB_L_REFRESH_IMAGE', Value = '15', Type = 'integer', DefaultValue = '15', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the watched image is refreshed (if not streaming)', Help = 'The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 180, Name = 'ZM_WEB_L_REFRESH_STATUS', Value = '10', Type = 'integer', DefaultValue = '10', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the status refreshes itself in the watch window', Help = 'The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 181, Name = 'ZM_WEB_L_REFRESH_EVENTS', Value = '180', Type = 'integer', DefaultValue = '180', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How often (in seconds) the event listing is refreshed in the watch window', Help = 'The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 182, Name = 'ZM_WEB_L_CAN_STREAM', Value = 'auto', Type = 'string', DefaultValue = 'auto', Hint = 'auto|yes|no', Pattern = '(?^i:^([ayn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : ($1 =~ /^n/ ? \"no\" : \"auto\" ) ', Prompt = 'Override the automatic detection of browser streaming capability', Help = 'If you know that your browser can handle image streams of the type \'multipart/x-mixed-replace\' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting \'yes\' will tell ZoneMinder that your browser can handle the streams natively, \'no\' means that it can\'t and so the plugin will be used while \'auto\' lets ZoneMinder decide.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 183, Name = 'ZM_WEB_L_STREAM_METHOD', Value = 'jpeg', Type = 'string', DefaultValue = 'jpeg', Hint = 'mpeg|jpeg', Pattern = '(?^i:^([mj]))', Format = ' $1 =~ /^m/ ? \"mpeg\" : \"jpeg\" ', Prompt = 'Which method should be used to send video streams to your browser.', Help = 'ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 184, Name = 'ZM_WEB_L_DEFAULT_SCALE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|33|50|75|100|150|200|300|400', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'live\' or \'event\' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 185, Name = 'ZM_WEB_L_DEFAULT_RATE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|50|100|150|200|400|1000|2500|5000|10000', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default replay rate factor applied to \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'event\' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 186, Name = 'ZM_WEB_L_VIDEO_BITRATE', Value = '25000', Type = 'integer', DefaultValue = '25000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the bitrate of the video encoded stream should be set to', Help = 'When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a \'quality\' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 187, Name = 'ZM_WEB_L_VIDEO_MAXFPS', Value = '5', Type = 'integer', DefaultValue = '5', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the maximum frame rate for streamed video should be', Help = 'When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 188, Name = 'ZM_WEB_L_SCALE_THUMBS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Scale thumbnails in events, bandwidth versus cpu in rescaling', Help = 'If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 189, Name = 'ZM_WEB_L_EVENTS_VIEW', Value = 'events', Type = 'string', DefaultValue = 'events', Hint = 'events|timeline', Pattern = '(?^i:^([lt]))', Format = ' $1 =~ /^e/ ? \"events\" : \"timeline\" ', Prompt = 'What the default view of multiple events should be.', Help = 'Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 190, Name = 'ZM_WEB_L_SHOW_PROGRESS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Show the progress of replay in event view.', Help = 'When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 191, Name = 'ZM_WEB_L_AJAX_TIMEOUT', Value = '10000', Type = 'integer', DefaultValue = '10000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to wait for Ajax request responses (ms)', Help = 'The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.', Category = 'lowband', Readonly = '0', Requires = ''; +insert into Config set Id = 192, Name = 'ZM_WEB_P_CAN_STREAM', Value = 'auto', Type = 'string', DefaultValue = 'auto', Hint = 'auto|yes|no', Pattern = '(?^i:^([ayn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : ($1 =~ /^n/ ? \"no\" : \"auto\" ) ', Prompt = 'Override the automatic detection of browser streaming capability', Help = 'If you know that your browser can handle image streams of the type \'multipart/x-mixed-replace\' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting \'yes\' will tell ZoneMinder that your browser can handle the streams natively, \'no\' means that it can\'t and so the plugin will be used while \'auto\' lets ZoneMinder decide.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 193, Name = 'ZM_WEB_P_STREAM_METHOD', Value = 'jpeg', Type = 'string', DefaultValue = 'jpeg', Hint = 'mpeg|jpeg', Pattern = '(?^i:^([mj]))', Format = ' $1 =~ /^m/ ? \"mpeg\" : \"jpeg\" ', Prompt = 'Which method should be used to send video streams to your browser.', Help = 'ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 194, Name = 'ZM_WEB_P_DEFAULT_SCALE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|33|50|75|100|150|200|300|400', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default scaling factor applied to \'live\' or \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'live\' or \'event\' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 195, Name = 'ZM_WEB_P_DEFAULT_RATE', Value = '100', Type = 'integer', DefaultValue = '100', Hint = '25|50|100|150|200|400|1000|2500|5000|10000', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the default replay rate factor applied to \'event\' views is (%)', Help = 'Normally ZoneMinder will display \'event\' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 196, Name = 'ZM_WEB_P_VIDEO_BITRATE', Value = '8000', Type = 'integer', DefaultValue = '8000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the bitrate of the video encoded stream should be set to', Help = 'When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a \'quality\' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 197, Name = 'ZM_WEB_P_VIDEO_MAXFPS', Value = '5', Type = 'integer', DefaultValue = '5', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'What the maximum frame rate for streamed video should be', Help = 'When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 198, Name = 'ZM_WEB_P_SCALE_THUMBS', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Scale thumbnails in events, bandwidth versus cpu in rescaling', Help = 'If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 199, Name = 'ZM_WEB_P_AJAX_TIMEOUT', Value = '10000', Type = 'integer', DefaultValue = '10000', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'How long to wait for Ajax request responses (ms)', Help = 'The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.', Category = 'phoneband', Readonly = '0', Requires = ''; +insert into Config set Id = 200, Name = 'ZM_DYN_LAST_VERSION', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What the last version of ZoneMinder recorded from zoneminder.com is', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 201, Name = 'ZM_DYN_CURR_VERSION', Value = '1.25.0', Type = 'string', DefaultValue = '1.25.0', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What the effective current version of ZoneMinder is, might be different from actual if versions ignored', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 202, Name = 'ZM_DYN_DB_VERSION', Value = '1.25.0', Type = 'string', DefaultValue = '1.25.0', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'What the version of the database is, from zmupdate', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 203, Name = 'ZM_DYN_LAST_CHECK', Value = '', Type = 'integer', DefaultValue = '', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'When the last check for version from zoneminder.com was', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 204, Name = 'ZM_DYN_NEXT_REMINDER', Value = '', Type = 'string', DefaultValue = '', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'When the earliest time to remind about versions will be', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 205, Name = 'ZM_DYN_DONATE_REMINDER_TIME', Value = '0', Type = 'integer', DefaultValue = '0', Hint = 'integer', Pattern = '(?^:^(\d+)$)', Format = ' $1 ', Prompt = 'When the earliest time to remind about donations will be', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 206, Name = 'ZM_DYN_SHOW_DONATE_REMINDER', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Remind about donations or not', Help = '', Category = 'dynamic', Readonly = '1', Requires = ''; +insert into Config set Id = 207, Name = 'ZM_EYEZM_DEBUG', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Switch additional debugging on for eyeZm Plugin', Help = 'Enable or Disable extra debugging from the eyeZm Plugin. Extra debugging information will be displayed in it\'s own file (EYEZM_LOG_TO_FILE is set), or your Apache error log', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 208, Name = 'ZM_EYEZM_LOG_TO_FILE', Value = '1', Type = 'boolean', DefaultValue = 'yes', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'When eyeZm Debugging is enabled, enabling this logs output to it\'s own file', Help = 'When EYEZM_DEBUG is on and EYEZM_LOG_TO_FILE is on, output generated from the eyeZm Plugin will go to it\'s own file. Otherwise it will go to the apache error log.', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 209, Name = 'ZM_EYEZM_LOG_FILE', Value = '/var/log/zm/zm_xml.log', Type = 'string', DefaultValue = '/var/log/zm/zm_xml.log', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Default filename to use when logging eyeZm Output and EYEZM_LOG_TO_FILE is enabled', Help = 'This file will contain it\'s own output from the eyeZm Plugin when EYEZM_LOG_TO_FILE and EYEZM_DEBUG are both enabled', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 210, Name = 'ZM_EYEZM_EVENT_VCODEC', Value = 'mpeg4', Type = 'string', DefaultValue = 'mpeg4', Hint = 'mpeg4|h264', Pattern = '(?^i:^([mh]))', Format = ' $1 =~ /^m/ ? \"mpeg4\" : \"h264\" ', Prompt = 'Default video-codec to use for encoding events', Help = 'The eyeZm Plugin calls FFMPEG externally to encode the captured images. If your FFMPEG is not built with support for H264, change this to MPEG-4. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+).', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 211, Name = 'ZM_EYEZM_FEED_VCODEC', Value = 'mjpeg', Type = 'string', DefaultValue = 'mjpeg', Hint = 'mjpeg|h264', Pattern = '(?^i:^([mh]))', Format = ' $1 =~ /^m/ ? \"mjpeg\" : \"h264\" ', Prompt = 'Default video-codec to use for streaming the live feed', Help = 'Determines whether the live stream is generated using native MJPEG streaming with ZoneMinder, or H264 using FFMPEG and HTML-5 streaming. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+). This is just a default parameter, and can be overridden with eyeZm.', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 212, Name = 'ZM_EYEZM_H264_DEFAULT_BR', Value = '96k', Type = 'string', DefaultValue = '96k', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Default bit-rate to use with FFMPEG for H264 streaming', Help = 'When using the eyeZm Plugin to stream H264 data, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 213, Name = 'ZM_EYEZM_H264_DEFAULT_EVBR', Value = '128k', Type = 'string', DefaultValue = '128k', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Default bit-rate to use with FFMPEG for H264 event viewing', Help = 'When using the eyeZm Plugin to view events in H264, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 214, Name = 'ZM_EYEZM_H264_TIMEOUT', Value = '20', Type = 'string', DefaultValue = '20', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Timeout (sec) to wait for H264 stream to start before terminating', Help = 'The eyeZm Plugin will attempt to spawn an H264 stream when requested, and require that it complete within the timeout specified. If you have a slow system or find through the logs that the H264 stream is not starting because the timeout is expiring, even though FFMPEG is running, try increasing this value. If you have a fast system, decreasing this value can improve the responsiveness when there are issues starting H264 streams', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 215, Name = 'ZM_EYEZM_SEG_DURATION', Value = '3', Type = 'string', DefaultValue = '3', Hint = 'string', Pattern = '(?^:^(.+)$)', Format = ' $1 ', Prompt = 'Segment duration used for streaming using HTTP-5 Streaming protocol', Help = 'The HTTP-5 Live Streaming Protocol segments the input video stream into small chunks of a duration specified by this parameter. Increasing the segment duration will help with choppy connections on the other end, but will increase the latency in starting a stream.', Category = 'eyeZm', Readonly = '0', Requires = ''; +insert into Config set Id = 216, Name = 'ZM_PATH_PLUGINS', Value = '/usr/share/zm', Type = 'string', DefaultValue = '/usr/share/zm', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to the plugin folder', Help = '3d-party plugins have to be placed here.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 217, Name = 'ZM_PLUGIN_EXTENSION', Value = '.zmpl', Type = 'string', DefaultValue = '.zmpl', Hint = 'relative/path/to/somewhere', Pattern = '(?^:^((?:[^/].*)?)/?$)', Format = ' $1 ', Prompt = 'Default extension of plugins to found.', Help = 'Default extension of plugins to found.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 218, Name = 'ZM_PLUGINS_CONFIG_PATH', Value = '/usr/share/zm/plugins.conf', Type = 'string', DefaultValue = '/usr/share/zm/plugins.conf', Hint = '/absolute/path/to/somewhere', Pattern = '(?^:^((?:/[^/]*)+?)/?$)', Format = ' $1 ', Prompt = 'Path to the config file for plugins.', Help = 'Path to the config file for plugins.', Category = 'paths', Readonly = '0', Requires = ''; +insert into Config set Id = 219, Name = 'ZM_LOAD_PLUGINS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Load and use 3d-party plugins', Help = '3d-party plugins will be loaded and used for analysing.', Category = 'config', Readonly = '0', Requires = ''; +insert into Config set Id = 220, Name = 'ZM_TURNOFF_NATIVE_ANALYSIS', Value = '0', Type = 'boolean', DefaultValue = 'no', Hint = 'yes|no', Pattern = '(?^i:^([yn]))', Format = ' ($1 =~ /^y/) ? \"yes\" : \"no\" ', Prompt = 'Turn native ZM\'s image analysis possibility off', Help = 'Image analysis with ZM\'s motion detected function will be turned off. Only detection functions from loaded plugins will be used. Note, that if no plugins have be loaded, no detection will be done.', Category = 'config', Readonly = '0', Requires = ''; + diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in new file mode 100644 index 000000000..c68616c04 --- /dev/null +++ b/db/zm_create.sql.in @@ -0,0 +1,623 @@ +-- MySQL dump 10.9 +-- +-- Host: localhost Database: @ZM_DB_NAME@ +-- ------------------------------------------------------ +-- Server version 4.1.16-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `@ZM_DB_NAME@` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `@ZM_DB_NAME@`; + +USE `@ZM_DB_NAME@`; + +-- +-- Table structure for table `Config` +-- + +DROP TABLE IF EXISTS `Config`; +CREATE TABLE `Config` ( + `Id` smallint(5) unsigned NOT NULL default '0', + `Name` varchar(32) NOT NULL default '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `DefaultValue` tinytext, + `Hint` tinytext, + `Pattern` tinytext, + `Format` tinytext, + `Prompt` tinytext, + `Help` text, + `Category` varchar(32) NOT NULL default '', + `Readonly` tinyint(3) unsigned NOT NULL default '0', + `Requires` text, + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `ControlPresets` +-- + +DROP TABLE IF EXISTS `ControlPresets`; +CREATE TABLE `ControlPresets` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Preset` int(10) unsigned NOT NULL default '0', + `Label` varchar(64) NOT NULL default '', + PRIMARY KEY (`MonitorId`,`Preset`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Controls` +-- + +DROP TABLE IF EXISTS `Controls`; +CREATE TABLE `Controls` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote') NOT NULL default 'Local', + `Protocol` varchar(64) default NULL, + `CanWake` tinyint(3) unsigned NOT NULL default '0', + `CanSleep` tinyint(3) unsigned NOT NULL default '0', + `CanReset` tinyint(3) unsigned NOT NULL default '0', + `CanZoom` tinyint(3) unsigned NOT NULL default '0', + `CanAutoZoom` tinyint(3) unsigned NOT NULL default '0', + `CanZoomAbs` tinyint(3) unsigned NOT NULL default '0', + `CanZoomRel` tinyint(3) unsigned NOT NULL default '0', + `CanZoomCon` tinyint(3) unsigned NOT NULL default '0', + `MinZoomRange` int(10) unsigned default NULL, + `MaxZoomRange` int(10) unsigned default NULL, + `MinZoomStep` int(10) unsigned default NULL, + `MaxZoomStep` int(10) unsigned default NULL, + `HasZoomSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinZoomSpeed` int(10) unsigned default NULL, + `MaxZoomSpeed` int(10) unsigned default NULL, + `CanFocus` tinyint(3) unsigned NOT NULL default '0', + `CanAutoFocus` tinyint(3) unsigned NOT NULL default '0', + `CanFocusAbs` tinyint(3) unsigned NOT NULL default '0', + `CanFocusRel` tinyint(3) unsigned NOT NULL default '0', + `CanFocusCon` tinyint(3) unsigned NOT NULL default '0', + `MinFocusRange` int(10) unsigned default NULL, + `MaxFocusRange` int(10) unsigned default NULL, + `MinFocusStep` int(10) unsigned default NULL, + `MaxFocusStep` int(10) unsigned default NULL, + `HasFocusSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinFocusSpeed` int(10) unsigned default NULL, + `MaxFocusSpeed` int(10) unsigned default NULL, + `CanIris` tinyint(3) unsigned NOT NULL default '0', + `CanAutoIris` tinyint(3) unsigned NOT NULL default '0', + `CanIrisAbs` tinyint(3) unsigned NOT NULL default '0', + `CanIrisRel` tinyint(3) unsigned NOT NULL default '0', + `CanIrisCon` tinyint(3) unsigned NOT NULL default '0', + `MinIrisRange` int(10) unsigned default NULL, + `MaxIrisRange` int(10) unsigned default NULL, + `MinIrisStep` int(10) unsigned default NULL, + `MaxIrisStep` int(10) unsigned default NULL, + `HasIrisSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinIrisSpeed` int(10) unsigned default NULL, + `MaxIrisSpeed` int(10) unsigned default NULL, + `CanGain` tinyint(3) unsigned NOT NULL default '0', + `CanAutoGain` tinyint(3) unsigned NOT NULL default '0', + `CanGainAbs` tinyint(3) unsigned NOT NULL default '0', + `CanGainRel` tinyint(3) unsigned NOT NULL default '0', + `CanGainCon` tinyint(3) unsigned NOT NULL default '0', + `MinGainRange` int(10) unsigned default NULL, + `MaxGainRange` int(10) unsigned default NULL, + `MinGainStep` int(10) unsigned default NULL, + `MaxGainStep` int(10) unsigned default NULL, + `HasGainSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinGainSpeed` int(10) unsigned default NULL, + `MaxGainSpeed` int(10) unsigned default NULL, + `CanWhite` tinyint(3) unsigned NOT NULL default '0', + `CanAutoWhite` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteAbs` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteRel` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteCon` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteRange` int(10) unsigned default NULL, + `MaxWhiteRange` int(10) unsigned default NULL, + `MinWhiteStep` int(10) unsigned default NULL, + `MaxWhiteStep` int(10) unsigned default NULL, + `HasWhiteSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteSpeed` int(10) unsigned default NULL, + `MaxWhiteSpeed` int(10) unsigned default NULL, + `HasPresets` tinyint(3) unsigned NOT NULL default '0', + `NumPresets` tinyint(3) unsigned NOT NULL default '0', + `HasHomePreset` tinyint(3) unsigned NOT NULL default '0', + `CanSetPresets` tinyint(3) unsigned NOT NULL default '0', + `CanMove` tinyint(3) unsigned NOT NULL default '0', + `CanMoveDiag` tinyint(3) unsigned NOT NULL default '0', + `CanMoveMap` tinyint(3) unsigned NOT NULL default '0', + `CanMoveAbs` tinyint(3) unsigned NOT NULL default '0', + `CanMoveRel` tinyint(3) unsigned NOT NULL default '0', + `CanMoveCon` tinyint(3) unsigned NOT NULL default '0', + `CanPan` tinyint(3) unsigned NOT NULL default '0', + `MinPanRange` int(10) default NULL, + `MaxPanRange` int(10) default NULL, + `MinPanStep` int(10) default NULL, + `MaxPanStep` int(10) default NULL, + `HasPanSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinPanSpeed` int(10) default NULL, + `MaxPanSpeed` int(10) default NULL, + `HasTurboPan` tinyint(3) unsigned NOT NULL default '0', + `TurboPanSpeed` int(10) default NULL, + `CanTilt` tinyint(3) unsigned NOT NULL default '0', + `MinTiltRange` int(10) default NULL, + `MaxTiltRange` int(10) default NULL, + `MinTiltStep` int(10) default NULL, + `MaxTiltStep` int(10) default NULL, + `HasTiltSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinTiltSpeed` int(10) default NULL, + `MaxTiltSpeed` int(10) default NULL, + `HasTurboTilt` tinyint(3) unsigned NOT NULL default '0', + `TurboTiltSpeed` int(10) default NULL, + `CanAutoScan` tinyint(3) unsigned NOT NULL default '0', + `NumScanPaths` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Devices` +-- + +DROP TABLE IF EXISTS `Devices`; +CREATE TABLE `Devices` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` tinytext NOT NULL, + `Type` enum('X10') NOT NULL default 'X10', + `KeyString` varchar(32) NOT NULL default '', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Events` +-- + +DROP TABLE IF EXISTS `Events`; +CREATE TABLE `Events` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Cause` varchar(32) NOT NULL default '', + `StartTime` datetime default NULL, + `EndTime` datetime default NULL, + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Length` decimal(10,2) NOT NULL default '0.00', + `Frames` int(10) unsigned default NULL, + `AlarmFrames` int(10) unsigned default NULL, + `TotScore` int(10) unsigned NOT NULL default '0', + `AvgScore` smallint(5) unsigned default '0', + `MaxScore` smallint(5) unsigned default '0', + `Archived` tinyint(3) unsigned NOT NULL default '0', + `Videoed` tinyint(3) unsigned NOT NULL default '0', + `Uploaded` tinyint(3) unsigned NOT NULL default '0', + `Emailed` tinyint(3) unsigned NOT NULL default '0', + `Messaged` tinyint(3) unsigned NOT NULL default '0', + `Executed` tinyint(3) unsigned NOT NULL default '0', + `Notes` text, + PRIMARY KEY (`Id`,`MonitorId`), + KEY `MonitorId` (`MonitorId`), + KEY `StartTime` (`StartTime`), + KEY `Frames` (`Frames`), + KEY `Archived` (`Archived`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Filters` +-- + +DROP TABLE IF EXISTS `Filters`; +CREATE TABLE `Filters` ( + `Name` varchar(64) NOT NULL default '', + `Query` text NOT NULL, + `AutoArchive` tinyint(3) unsigned NOT NULL default '0', + `AutoVideo` tinyint(3) unsigned NOT NULL default '0', + `AutoUpload` tinyint(3) unsigned NOT NULL default '0', + `AutoEmail` tinyint(3) unsigned NOT NULL default '0', + `AutoMessage` tinyint(3) unsigned NOT NULL default '0', + `AutoExecute` tinyint(3) unsigned NOT NULL default '0', + `AutoExecuteCmd` tinytext, + `AutoDelete` tinyint(3) unsigned NOT NULL default '0', + `Background` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Frames` +-- + +DROP TABLE IF EXISTS `Frames`; +CREATE TABLE `Frames` ( + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `Type` enum('Normal','Bulk','Alarm') NOT NULL default 'Normal', + `TimeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `Delta` decimal(8,2) NOT NULL default '0.00', + `Score` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`EventId`,`FrameId`), + KEY `Type` (`Type`), + KEY `TimeStamp` (`TimeStamp`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Groups` +-- + +DROP TABLE IF EXISTS `Groups`; +CREATE TABLE `Groups` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Logs` +-- +CREATE TABLE `Logs` ( + `TimeKey` decimal(16,6) NOT NULL, + `Component` varchar(32) NOT NULL, + `Pid` smallint(6) DEFAULT NULL, + `Level` tinyint(3) NOT NULL, + `Code` char(3) NOT NULL, + `Message` varchar(255) NOT NULL, + `File` varchar(255) DEFAULT NULL, + `Line` smallint(5) unsigned DEFAULT NULL, + KEY `TimeKey` (`TimeKey`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `MonitorPresets` +-- + +DROP TABLE IF EXISTS `MonitorPresets`; +CREATE TABLE `MonitorPresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Device` tinytext, + `Channel` tinyint(3) unsigned default NULL, + `Format` int(10) unsigned default NULL, + `Protocol` varchar(16) default NULL, + `Method` varchar(16) default NULL, + `Host` varchar(64) default NULL, + `Port` varchar(8) default NULL, + `Path` varchar(255) default NULL, + `SubPath` varchar(64) default NULL, + `Width` smallint(5) unsigned default NULL, + `Height` smallint(5) unsigned default NULL, + `Palette` int(10) unsigned default NULL, + `MaxFPS` decimal(5,2) default NULL, + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` varchar(16) default NULL, + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Monitors` +-- + +DROP TABLE IF EXISTS `Monitors`; +CREATE TABLE `Monitors` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `LinkedMonitors` varchar(255) NOT NULL default '', + `Triggers` set('X10') NOT NULL default '', + `Device` varchar(64) NOT NULL default '', + `Channel` tinyint(3) unsigned NOT NULL default '0', + `Format` int(10) unsigned NOT NULL default '0', + `Protocol` varchar(16) NOT NULL default '', + `Method` varchar(16) NOT NULL default '', + `Host` varchar(64) NOT NULL default '', + `Port` varchar(8) NOT NULL default '', + `SubPath` varchar(64) NOT NULL default '', + `Path` varchar(255) NOT NULL default '', + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Colours` tinyint(3) unsigned NOT NULL default '1', + `Palette` int(10) unsigned NOT NULL default '0', + `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', + `Deinterlacing` int(10) unsigned NOT NULL default '0', + `Brightness` mediumint(7) NOT NULL default '-1', + `Contrast` mediumint(7) NOT NULL default '-1', + `Hue` mediumint(7) NOT NULL default '-1', + `Colour` mediumint(7) NOT NULL default '-1', + `EventPrefix` varchar(32) NOT NULL default 'Event-', + `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S', + `LabelX` smallint(5) unsigned NOT NULL default '0', + `LabelY` smallint(5) unsigned NOT NULL default '0', + `ImageBufferCount` smallint(5) unsigned NOT NULL default '100', + `WarmupCount` smallint(5) unsigned NOT NULL default '25', + `PreEventCount` smallint(5) unsigned NOT NULL default '10', + `PostEventCount` smallint(5) unsigned NOT NULL default '10', + `StreamReplayBuffer` int(10) unsigned NOT NULL default '1000', + `AlarmFrameCount` smallint(5) unsigned NOT NULL default '1', + `SectionLength` int(10) unsigned NOT NULL default '600', + `FrameSkip` smallint(5) unsigned NOT NULL default '0', + `MaxFPS` decimal(5,2) default NULL, + `AlarmMaxFPS` decimal(5,2) default NULL, + `FPSReportInterval` smallint(5) unsigned NOT NULL default '250', + `RefBlendPerc` tinyint(3) unsigned NOT NULL default '10', + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` int(10) unsigned NOT NULL default '0', + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `AutoStopTimeout` decimal(5,2) default NULL, + `TrackMotion` tinyint(3) unsigned NOT NULL default '0', + `TrackDelay` smallint(5) unsigned NOT NULL default '0', + `ReturnLocation` tinyint(3) NOT NULL default '-1', + `ReturnDelay` smallint(5) unsigned NOT NULL default '0', + `DefaultView` enum('Events','Control') NOT NULL default 'Events', + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + `SignalCheckColour` varchar(32) NOT NULL default '#0000BE', + `WebColour` varchar(32) NOT NULL default 'red', + `Sequence` smallint(5) unsigned default NULL, + `UsedPl` varchar(88) NOT NULL default '', + `DoNativeMotDet` tinyint(3) unsigned NOT NULL default '1', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `States` +-- + +DROP TABLE IF EXISTS `States`; +CREATE TABLE `States` ( + `Name` varchar(64) NOT NULL default '', + `Definition` text NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Stats` +-- + +DROP TABLE IF EXISTS `Stats`; +CREATE TABLE `Stats` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `ZoneId` int(10) unsigned NOT NULL default '0', + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `PixelDiff` tinyint(3) unsigned NOT NULL default '0', + `AlarmPixels` int(10) unsigned NOT NULL default '0', + `FilterPixels` int(10) unsigned NOT NULL default '0', + `BlobPixels` int(10) unsigned NOT NULL default '0', + `Blobs` smallint(5) unsigned NOT NULL default '0', + `MinBlobSize` int(10) unsigned NOT NULL default '0', + `MaxBlobSize` int(10) unsigned NOT NULL default '0', + `MinX` smallint(5) unsigned NOT NULL default '0', + `MaxX` smallint(5) unsigned NOT NULL default '0', + `MinY` smallint(5) unsigned NOT NULL default '0', + `MaxY` smallint(5) unsigned NOT NULL default '0', + `Score` smallint(5) unsigned NOT NULL default '0', + KEY `EventId` (`EventId`), + KEY `MonitorId` (`MonitorId`), + KEY `ZoneId` (`ZoneId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `TriggersX10` +-- + +DROP TABLE IF EXISTS `TriggersX10`; +CREATE TABLE `TriggersX10` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Activation` varchar(32) default NULL, + `AlarmInput` varchar(32) default NULL, + `AlarmOutput` varchar(32) default NULL, + PRIMARY KEY (`MonitorId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Users` +-- + +DROP TABLE IF EXISTS `Users`; +CREATE TABLE `Users` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '', + `Password` varchar(64) NOT NULL default '', + `Language` varchar(8) NOT NULL default '', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `Stream` enum('None','View') NOT NULL default 'None', + `Events` enum('None','View','Edit') NOT NULL default 'None', + `Control` enum('None','View','Edit') NOT NULL default 'None', + `Monitors` enum('None','View','Edit') NOT NULL default 'None', + `Devices` enum('None','View','Edit') NOT NULL default 'None', + `System` enum('None','View','Edit') NOT NULL default 'None', + `MaxBandwidth` varchar(16) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`), + UNIQUE KEY `UC_Username` (`Username`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `ZonePresets` +-- + +DROP TABLE IF EXISTS `ZonePresets`; +CREATE TABLE `ZonePresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Zones` +-- + +DROP TABLE IF EXISTS `Zones`; +CREATE TABLE `Zones` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `NumCoords` tinyint(3) unsigned NOT NULL default '0', + `Coords` tinytext NOT NULL, + `Area` int(10) unsigned NOT NULL default '0', + `AlarmRGB` int(10) unsigned default '0', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`), + KEY `MonitorId` (`MonitorId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- +-- Initial data to be loaded into ZoneMinder database +-- + +-- +-- Create a default admin user. +-- +insert into Users values ('','admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','Edit','',''); + +-- +-- Add a sample filter to purge the oldest 5 events when the disk is 95% full, delete is disabled though +-- +insert into Filters values ('PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":5,"sort_asc":1}',0,0,0,0,0,0,'',1,0); + +-- +-- Add in some sample control protocol definitions +-- +insert into Controls values (1,'Pelco-D','Local','PelcoD',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (2,'Pelco-P','Local','PelcoP',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (3,'Sony VISCA','Local','Visca',1,1,0,1,0,0,0,1,0,16384,10,4000,1,1,6,1,1,1,0,1,0,1536,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,3,1,1,1,1,0,1,1,0,1,-15578,15578,100,10000,1,1,50,1,254,1,-7789,7789,100,5000,1,1,50,1,254,0,0); +INSERT INTO Controls VALUES (4,'Axis API v2','Remote','AxisV2',0,0,0,1,0,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,1,1,1,1,1,0,1,0,1,-360,360,1,90,0,NULL,NULL,0,NULL,1,-360,360,1,90,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (5,'Panasonic IP','Remote','PanasonicIP',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,8,1,1,1,0,1,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (6,'Neu-Fusion NCS370','Remote','Ncs370',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,24,1,0,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); + +-- +-- Add some monitor preset values +-- +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,1,4,NULL,':',100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, multicast','Remote',NULL,NULL,NULL,'rtsp','rtpMulti','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP','Remote',NULL,NULL,NULL,'rtsp','rtpRtsp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','VEO Observer, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Blue Net Video Server, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); + +-- +-- Add some zone preset values +-- +INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',60,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',40,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',20,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',60,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',40,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL,0); + +-- +-- Apply the initial configuration +-- +-- This section is autogenerated by zmconfgen.pl +-- Do not edit this file as any changes will be overwritten +-- diff --git a/db/zm_create.sql.in.orig b/db/zm_create.sql.in.orig new file mode 100644 index 000000000..0c48e7ca3 --- /dev/null +++ b/db/zm_create.sql.in.orig @@ -0,0 +1,621 @@ +-- MySQL dump 10.9 +-- +-- Host: localhost Database: @ZM_DB_NAME@ +-- ------------------------------------------------------ +-- Server version 4.1.16-log + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `@ZM_DB_NAME@` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `@ZM_DB_NAME@`; + +USE `@ZM_DB_NAME@`; + +-- +-- Table structure for table `Config` +-- + +DROP TABLE IF EXISTS `Config`; +CREATE TABLE `Config` ( + `Id` smallint(5) unsigned NOT NULL default '0', + `Name` varchar(32) NOT NULL default '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `DefaultValue` tinytext, + `Hint` tinytext, + `Pattern` tinytext, + `Format` tinytext, + `Prompt` tinytext, + `Help` text, + `Category` varchar(32) NOT NULL default '', + `Readonly` tinyint(3) unsigned NOT NULL default '0', + `Requires` text, + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `ControlPresets` +-- + +DROP TABLE IF EXISTS `ControlPresets`; +CREATE TABLE `ControlPresets` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Preset` int(10) unsigned NOT NULL default '0', + `Label` varchar(64) NOT NULL default '', + PRIMARY KEY (`MonitorId`,`Preset`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Controls` +-- + +DROP TABLE IF EXISTS `Controls`; +CREATE TABLE `Controls` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote') NOT NULL default 'Local', + `Protocol` varchar(64) default NULL, + `CanWake` tinyint(3) unsigned NOT NULL default '0', + `CanSleep` tinyint(3) unsigned NOT NULL default '0', + `CanReset` tinyint(3) unsigned NOT NULL default '0', + `CanZoom` tinyint(3) unsigned NOT NULL default '0', + `CanAutoZoom` tinyint(3) unsigned NOT NULL default '0', + `CanZoomAbs` tinyint(3) unsigned NOT NULL default '0', + `CanZoomRel` tinyint(3) unsigned NOT NULL default '0', + `CanZoomCon` tinyint(3) unsigned NOT NULL default '0', + `MinZoomRange` int(10) unsigned default NULL, + `MaxZoomRange` int(10) unsigned default NULL, + `MinZoomStep` int(10) unsigned default NULL, + `MaxZoomStep` int(10) unsigned default NULL, + `HasZoomSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinZoomSpeed` int(10) unsigned default NULL, + `MaxZoomSpeed` int(10) unsigned default NULL, + `CanFocus` tinyint(3) unsigned NOT NULL default '0', + `CanAutoFocus` tinyint(3) unsigned NOT NULL default '0', + `CanFocusAbs` tinyint(3) unsigned NOT NULL default '0', + `CanFocusRel` tinyint(3) unsigned NOT NULL default '0', + `CanFocusCon` tinyint(3) unsigned NOT NULL default '0', + `MinFocusRange` int(10) unsigned default NULL, + `MaxFocusRange` int(10) unsigned default NULL, + `MinFocusStep` int(10) unsigned default NULL, + `MaxFocusStep` int(10) unsigned default NULL, + `HasFocusSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinFocusSpeed` int(10) unsigned default NULL, + `MaxFocusSpeed` int(10) unsigned default NULL, + `CanIris` tinyint(3) unsigned NOT NULL default '0', + `CanAutoIris` tinyint(3) unsigned NOT NULL default '0', + `CanIrisAbs` tinyint(3) unsigned NOT NULL default '0', + `CanIrisRel` tinyint(3) unsigned NOT NULL default '0', + `CanIrisCon` tinyint(3) unsigned NOT NULL default '0', + `MinIrisRange` int(10) unsigned default NULL, + `MaxIrisRange` int(10) unsigned default NULL, + `MinIrisStep` int(10) unsigned default NULL, + `MaxIrisStep` int(10) unsigned default NULL, + `HasIrisSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinIrisSpeed` int(10) unsigned default NULL, + `MaxIrisSpeed` int(10) unsigned default NULL, + `CanGain` tinyint(3) unsigned NOT NULL default '0', + `CanAutoGain` tinyint(3) unsigned NOT NULL default '0', + `CanGainAbs` tinyint(3) unsigned NOT NULL default '0', + `CanGainRel` tinyint(3) unsigned NOT NULL default '0', + `CanGainCon` tinyint(3) unsigned NOT NULL default '0', + `MinGainRange` int(10) unsigned default NULL, + `MaxGainRange` int(10) unsigned default NULL, + `MinGainStep` int(10) unsigned default NULL, + `MaxGainStep` int(10) unsigned default NULL, + `HasGainSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinGainSpeed` int(10) unsigned default NULL, + `MaxGainSpeed` int(10) unsigned default NULL, + `CanWhite` tinyint(3) unsigned NOT NULL default '0', + `CanAutoWhite` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteAbs` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteRel` tinyint(3) unsigned NOT NULL default '0', + `CanWhiteCon` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteRange` int(10) unsigned default NULL, + `MaxWhiteRange` int(10) unsigned default NULL, + `MinWhiteStep` int(10) unsigned default NULL, + `MaxWhiteStep` int(10) unsigned default NULL, + `HasWhiteSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinWhiteSpeed` int(10) unsigned default NULL, + `MaxWhiteSpeed` int(10) unsigned default NULL, + `HasPresets` tinyint(3) unsigned NOT NULL default '0', + `NumPresets` tinyint(3) unsigned NOT NULL default '0', + `HasHomePreset` tinyint(3) unsigned NOT NULL default '0', + `CanSetPresets` tinyint(3) unsigned NOT NULL default '0', + `CanMove` tinyint(3) unsigned NOT NULL default '0', + `CanMoveDiag` tinyint(3) unsigned NOT NULL default '0', + `CanMoveMap` tinyint(3) unsigned NOT NULL default '0', + `CanMoveAbs` tinyint(3) unsigned NOT NULL default '0', + `CanMoveRel` tinyint(3) unsigned NOT NULL default '0', + `CanMoveCon` tinyint(3) unsigned NOT NULL default '0', + `CanPan` tinyint(3) unsigned NOT NULL default '0', + `MinPanRange` int(10) default NULL, + `MaxPanRange` int(10) default NULL, + `MinPanStep` int(10) default NULL, + `MaxPanStep` int(10) default NULL, + `HasPanSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinPanSpeed` int(10) default NULL, + `MaxPanSpeed` int(10) default NULL, + `HasTurboPan` tinyint(3) unsigned NOT NULL default '0', + `TurboPanSpeed` int(10) default NULL, + `CanTilt` tinyint(3) unsigned NOT NULL default '0', + `MinTiltRange` int(10) default NULL, + `MaxTiltRange` int(10) default NULL, + `MinTiltStep` int(10) default NULL, + `MaxTiltStep` int(10) default NULL, + `HasTiltSpeed` tinyint(3) unsigned NOT NULL default '0', + `MinTiltSpeed` int(10) default NULL, + `MaxTiltSpeed` int(10) default NULL, + `HasTurboTilt` tinyint(3) unsigned NOT NULL default '0', + `TurboTiltSpeed` int(10) default NULL, + `CanAutoScan` tinyint(3) unsigned NOT NULL default '0', + `NumScanPaths` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Devices` +-- + +DROP TABLE IF EXISTS `Devices`; +CREATE TABLE `Devices` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` tinytext NOT NULL, + `Type` enum('X10') NOT NULL default 'X10', + `KeyString` varchar(32) NOT NULL default '', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Events` +-- + +DROP TABLE IF EXISTS `Events`; +CREATE TABLE `Events` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Cause` varchar(32) NOT NULL default '', + `StartTime` datetime default NULL, + `EndTime` datetime default NULL, + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Length` decimal(10,2) NOT NULL default '0.00', + `Frames` int(10) unsigned default NULL, + `AlarmFrames` int(10) unsigned default NULL, + `TotScore` int(10) unsigned NOT NULL default '0', + `AvgScore` smallint(5) unsigned default '0', + `MaxScore` smallint(5) unsigned default '0', + `Archived` tinyint(3) unsigned NOT NULL default '0', + `Videoed` tinyint(3) unsigned NOT NULL default '0', + `Uploaded` tinyint(3) unsigned NOT NULL default '0', + `Emailed` tinyint(3) unsigned NOT NULL default '0', + `Messaged` tinyint(3) unsigned NOT NULL default '0', + `Executed` tinyint(3) unsigned NOT NULL default '0', + `Notes` text, + PRIMARY KEY (`Id`,`MonitorId`), + KEY `MonitorId` (`MonitorId`), + KEY `StartTime` (`StartTime`), + KEY `Frames` (`Frames`), + KEY `Archived` (`Archived`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Filters` +-- + +DROP TABLE IF EXISTS `Filters`; +CREATE TABLE `Filters` ( + `Name` varchar(64) NOT NULL default '', + `Query` text NOT NULL, + `AutoArchive` tinyint(3) unsigned NOT NULL default '0', + `AutoVideo` tinyint(3) unsigned NOT NULL default '0', + `AutoUpload` tinyint(3) unsigned NOT NULL default '0', + `AutoEmail` tinyint(3) unsigned NOT NULL default '0', + `AutoMessage` tinyint(3) unsigned NOT NULL default '0', + `AutoExecute` tinyint(3) unsigned NOT NULL default '0', + `AutoExecuteCmd` tinytext, + `AutoDelete` tinyint(3) unsigned NOT NULL default '0', + `Background` tinyint(1) unsigned NOT NULL default '0', + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Frames` +-- + +DROP TABLE IF EXISTS `Frames`; +CREATE TABLE `Frames` ( + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `Type` enum('Normal','Bulk','Alarm') NOT NULL default 'Normal', + `TimeStamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, + `Delta` decimal(8,2) NOT NULL default '0.00', + `Score` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`EventId`,`FrameId`), + KEY `Type` (`Type`), + KEY `TimeStamp` (`TimeStamp`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Groups` +-- + +DROP TABLE IF EXISTS `Groups`; +CREATE TABLE `Groups` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Logs` +-- +CREATE TABLE `Logs` ( + `TimeKey` decimal(16,6) NOT NULL, + `Component` varchar(32) NOT NULL, + `Pid` smallint(6) DEFAULT NULL, + `Level` tinyint(3) NOT NULL, + `Code` char(3) NOT NULL, + `Message` varchar(255) NOT NULL, + `File` varchar(255) DEFAULT NULL, + `Line` smallint(5) unsigned DEFAULT NULL, + KEY `TimeKey` (`TimeKey`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `MonitorPresets` +-- + +DROP TABLE IF EXISTS `MonitorPresets`; +CREATE TABLE `MonitorPresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Device` tinytext, + `Channel` tinyint(3) unsigned default NULL, + `Format` int(10) unsigned default NULL, + `Protocol` varchar(16) default NULL, + `Method` varchar(16) default NULL, + `Host` varchar(64) default NULL, + `Port` varchar(8) default NULL, + `Path` varchar(255) default NULL, + `SubPath` varchar(64) default NULL, + `Width` smallint(5) unsigned default NULL, + `Height` smallint(5) unsigned default NULL, + `Palette` int(10) unsigned default NULL, + `MaxFPS` decimal(5,2) default NULL, + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` varchar(16) default NULL, + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Monitors` +-- + +DROP TABLE IF EXISTS `Monitors`; +CREATE TABLE `Monitors` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local', + `Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `LinkedMonitors` varchar(255) NOT NULL default '', + `Triggers` set('X10') NOT NULL default '', + `Device` varchar(64) NOT NULL default '', + `Channel` tinyint(3) unsigned NOT NULL default '0', + `Format` int(10) unsigned NOT NULL default '0', + `Protocol` varchar(16) NOT NULL default '', + `Method` varchar(16) NOT NULL default '', + `Host` varchar(64) NOT NULL default '', + `Port` varchar(8) NOT NULL default '', + `SubPath` varchar(64) NOT NULL default '', + `Path` varchar(255) NOT NULL default '', + `Width` smallint(5) unsigned NOT NULL default '0', + `Height` smallint(5) unsigned NOT NULL default '0', + `Colours` tinyint(3) unsigned NOT NULL default '1', + `Palette` int(10) unsigned NOT NULL default '0', + `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', + `Deinterlacing` int(10) unsigned NOT NULL default '0', + `Brightness` mediumint(7) NOT NULL default '-1', + `Contrast` mediumint(7) NOT NULL default '-1', + `Hue` mediumint(7) NOT NULL default '-1', + `Colour` mediumint(7) NOT NULL default '-1', + `EventPrefix` varchar(32) NOT NULL default 'Event-', + `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S', + `LabelX` smallint(5) unsigned NOT NULL default '0', + `LabelY` smallint(5) unsigned NOT NULL default '0', + `ImageBufferCount` smallint(5) unsigned NOT NULL default '100', + `WarmupCount` smallint(5) unsigned NOT NULL default '25', + `PreEventCount` smallint(5) unsigned NOT NULL default '10', + `PostEventCount` smallint(5) unsigned NOT NULL default '10', + `StreamReplayBuffer` int(10) unsigned NOT NULL default '1000', + `AlarmFrameCount` smallint(5) unsigned NOT NULL default '1', + `SectionLength` int(10) unsigned NOT NULL default '600', + `FrameSkip` smallint(5) unsigned NOT NULL default '0', + `MaxFPS` decimal(5,2) default NULL, + `AlarmMaxFPS` decimal(5,2) default NULL, + `FPSReportInterval` smallint(5) unsigned NOT NULL default '250', + `RefBlendPerc` tinyint(3) unsigned NOT NULL default '10', + `Controllable` tinyint(3) unsigned NOT NULL default '0', + `ControlId` int(10) unsigned NOT NULL default '0', + `ControlDevice` varchar(255) default NULL, + `ControlAddress` varchar(255) default NULL, + `AutoStopTimeout` decimal(5,2) default NULL, + `TrackMotion` tinyint(3) unsigned NOT NULL default '0', + `TrackDelay` smallint(5) unsigned NOT NULL default '0', + `ReturnLocation` tinyint(3) NOT NULL default '-1', + `ReturnDelay` smallint(5) unsigned NOT NULL default '0', + `DefaultView` enum('Events','Control') NOT NULL default 'Events', + `DefaultRate` smallint(5) unsigned NOT NULL default '100', + `DefaultScale` smallint(5) unsigned NOT NULL default '100', + `SignalCheckColour` varchar(32) NOT NULL default '#0000BE', + `WebColour` varchar(32) NOT NULL default 'red', + `Sequence` smallint(5) unsigned default NULL, + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `States` +-- + +DROP TABLE IF EXISTS `States`; +CREATE TABLE `States` ( + `Name` varchar(64) NOT NULL default '', + `Definition` text NOT NULL, + PRIMARY KEY (`Name`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Stats` +-- + +DROP TABLE IF EXISTS `Stats`; +CREATE TABLE `Stats` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `ZoneId` int(10) unsigned NOT NULL default '0', + `EventId` int(10) unsigned NOT NULL default '0', + `FrameId` int(10) unsigned NOT NULL default '0', + `PixelDiff` tinyint(3) unsigned NOT NULL default '0', + `AlarmPixels` int(10) unsigned NOT NULL default '0', + `FilterPixels` int(10) unsigned NOT NULL default '0', + `BlobPixels` int(10) unsigned NOT NULL default '0', + `Blobs` smallint(5) unsigned NOT NULL default '0', + `MinBlobSize` int(10) unsigned NOT NULL default '0', + `MaxBlobSize` int(10) unsigned NOT NULL default '0', + `MinX` smallint(5) unsigned NOT NULL default '0', + `MaxX` smallint(5) unsigned NOT NULL default '0', + `MinY` smallint(5) unsigned NOT NULL default '0', + `MaxY` smallint(5) unsigned NOT NULL default '0', + `Score` smallint(5) unsigned NOT NULL default '0', + KEY `EventId` (`EventId`), + KEY `MonitorId` (`MonitorId`), + KEY `ZoneId` (`ZoneId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `TriggersX10` +-- + +DROP TABLE IF EXISTS `TriggersX10`; +CREATE TABLE `TriggersX10` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Activation` varchar(32) default NULL, + `AlarmInput` varchar(32) default NULL, + `AlarmOutput` varchar(32) default NULL, + PRIMARY KEY (`MonitorId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Users` +-- + +DROP TABLE IF EXISTS `Users`; +CREATE TABLE `Users` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Username` varchar(32) character set latin1 collate latin1_bin NOT NULL default '', + `Password` varchar(64) NOT NULL default '', + `Language` varchar(8) NOT NULL default '', + `Enabled` tinyint(3) unsigned NOT NULL default '1', + `Stream` enum('None','View') NOT NULL default 'None', + `Events` enum('None','View','Edit') NOT NULL default 'None', + `Control` enum('None','View','Edit') NOT NULL default 'None', + `Monitors` enum('None','View','Edit') NOT NULL default 'None', + `Devices` enum('None','View','Edit') NOT NULL default 'None', + `System` enum('None','View','Edit') NOT NULL default 'None', + `MaxBandwidth` varchar(16) NOT NULL default '', + `MonitorIds` tinytext NOT NULL, + PRIMARY KEY (`Id`), + UNIQUE KEY `UC_Username` (`Username`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `ZonePresets` +-- + +DROP TABLE IF EXISTS `ZonePresets`; +CREATE TABLE `ZonePresets` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +-- +-- Table structure for table `Zones` +-- + +DROP TABLE IF EXISTS `Zones`; +CREATE TABLE `Zones` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `MonitorId` int(10) unsigned NOT NULL default '0', + `Name` varchar(64) NOT NULL default '', + `Type` enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + `Units` enum('Pixels','Percent') NOT NULL default 'Pixels', + `NumCoords` tinyint(3) unsigned NOT NULL default '0', + `Coords` tinytext NOT NULL, + `Area` int(10) unsigned NOT NULL default '0', + `AlarmRGB` int(10) unsigned default '0', + `CheckMethod` enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + `MinPixelThreshold` smallint(5) unsigned default NULL, + `MaxPixelThreshold` smallint(5) unsigned default NULL, + `MinAlarmPixels` int(10) unsigned default NULL, + `MaxAlarmPixels` int(10) unsigned default NULL, + `FilterX` tinyint(3) unsigned default NULL, + `FilterY` tinyint(3) unsigned default NULL, + `MinFilterPixels` int(10) unsigned default NULL, + `MaxFilterPixels` int(10) unsigned default NULL, + `MinBlobPixels` int(10) unsigned default NULL, + `MaxBlobPixels` int(10) unsigned default NULL, + `MinBlobs` smallint(5) unsigned default NULL, + `MaxBlobs` smallint(5) unsigned default NULL, + `OverloadFrames` smallint(5) unsigned NOT NULL default '0', + PRIMARY KEY (`Id`), + KEY `MonitorId` (`MonitorId`) +) ENGINE=@ZM_MYSQL_ENGINE@; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- +-- Initial data to be loaded into ZoneMinder database +-- + +-- +-- Create a default admin user. +-- +insert into Users values ('','admin',password('admin'),'',1,'View','Edit','Edit','Edit','Edit','Edit','',''); + +-- +-- Add a sample filter to purge the oldest 5 events when the disk is 95% full, delete is disabled though +-- +insert into Filters values ('PurgeWhenFull','{"sort_field":"Id","terms":[{"val":0,"attr":"Archived","op":"="},{"cnj":"and","val":95,"attr":"DiskPercent","op":">="}],"limit":5,"sort_asc":1}',0,0,0,0,0,0,'',1,0); + +-- +-- Add in some sample control protocol definitions +-- +insert into Controls values (1,'Pelco-D','Local','PelcoD',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (2,'Pelco-P','Local','PelcoP',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (3,'Sony VISCA','Local','Visca',1,1,0,1,0,0,0,1,0,16384,10,4000,1,1,6,1,1,1,0,1,0,1536,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,3,1,1,1,1,0,1,1,0,1,-15578,15578,100,10000,1,1,50,1,254,1,-7789,7789,100,5000,1,1,50,1,254,0,0); +INSERT INTO Controls VALUES (4,'Axis API v2','Remote','AxisV2',0,0,0,1,0,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,1,1,1,1,1,0,1,0,1,-360,360,1,90,0,NULL,NULL,0,NULL,1,-360,360,1,90,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (5,'Panasonic IP','Remote','PanasonicIP',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,8,1,1,1,0,1,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (6,'Neu-Fusion NCS370','Remote','Ncs370',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,24,1,0,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); + +-- +-- Add some monitor preset values +-- +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, B&W','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',NULL,320,240,3,5.0,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',NULL,640,480,3,5.0,1,4,NULL,':',100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, multicast','Remote',NULL,NULL,NULL,'rtsp','rtpMulti','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP','Remote',NULL,NULL,NULL,'rtsp','rtpRtsp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',NULL,640,480,3,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg, max 5 FPS','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/GetData.cgi',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','VEO Observer, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Blue Net Video Server, jpeg','Remote','http','simple',NULL,NULL,NULL,'',80,'/cgi-bin/image.cgi?control=0&id=admin&passwd=admin',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT into MonitorPresets VALUES ('','ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); + +-- +-- Add some zone preset values +-- +INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',60,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',40,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',20,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0); +INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',60,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',40,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL,0); +INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL,0); + +-- +-- Apply the initial configuration +-- +-- This section is autogenerated by zmconfgen.pl +-- Do not edit this file as any changes will be overwritten +-- diff --git a/db/zm_update-0.0.1.sql b/db/zm_update-0.0.1.sql new file mode 100644 index 000000000..373afd273 --- /dev/null +++ b/db/zm_update-0.0.1.sql @@ -0,0 +1,62 @@ +-- +-- This updates a 0.0.1 database to 0.9.7 +-- +alter table Monitors modify Device tinyint unsigned NOT NULL default '0'; +alter table Monitors modify Format tinyint unsigned NOT NULL; +alter table Monitors drop column WarmUpCount; +alter table Monitors drop column PreEventCount; +alter table Monitors drop column PostEventCount; +alter table Monitors modify LabelFormat varchar(32) not null default '%%s - %y/%m/%d %H:%M:%S'; +alter table Monitors modify LabelX smallint unsigned not null; +alter table Monitors modify LabelY smallint unsigned not null; +alter table Monitors add column ImageBufferCount smallint unsigned NOT NULL default '100'; +alter table Monitors add column WarmupCount smallint unsigned NOT NULL default '25'; +alter table Monitors add column PreEventCount smallint unsigned NOT NULL default '10'; +alter table Monitors add column PostEventCount smallint unsigned NOT NULL default '10'; +alter table Monitors add column AlarmFrameCount smallint unsigned NOT NULL default '1'; +alter table Monitors add column FPSReportInterval smallint unsigned NOT NULL default '250'; +alter table Monitors add column RefBlendPerc tinyint unsigned NOT NULL default '10'; +alter table Monitors add column X10Activation char(32); +alter table Monitors add column X10AlarmInput char(32); +alter table Monitors add column X10AlarmOutput char(32); +alter table Monitors modify column Function enum('None','Passive','Active','X10') default 'Passive' not null; +update Monitors set LabelFormat = '%%s - %y/%m/%d %H:%M:%S'; +update Monitors set LabelX = 0; +update Monitors set LabelY = Height-8; +alter table Events add column TotScore int unsigned not null default 0 after AlarmFrames; +update Events set TotScore = AlarmFrames * AvgScore where TotScore = 0; +alter table Events modify column Archived tinyint unsigned not null default 0; +alter table Events add column Uploaded tinyint unsigned not null default 0 after Archived; +alter table Events add column LearnState char(1) default '' after Uploaded; +CREATE TABLE Filters ( +Id int(10) unsigned NOT NULL auto_increment, +MonitorId int(10) unsigned NOT NULL default '0', +Name varchar(64) NOT NULL default '', +Query text NOT NULL, +AutoDelete tinyint(4) unsigned NOT NULL default '0', +AutoUpload tinyint(4) unsigned NOT NULL default '0', +PRIMARY KEY (Id), +UNIQUE KEY FilterIDX (MonitorId,Name) +) TYPE=MyISAM; +CREATE TABLE Stats ( +MonitorId int(10) unsigned NOT NULL default '0', +ZoneId int(10) unsigned NOT NULL default '0', +EventId int(10) unsigned NOT NULL default '0', +FrameId int(10) unsigned NOT NULL default '0', +AlarmPixels int(10) unsigned NOT NULL default '0', +FilterPixels int(10) unsigned NOT NULL default '0', +BlobPixels int(10) unsigned NOT NULL default '0', +Blobs smallint(5) unsigned NOT NULL default '0', +MinBlobSize smallint(5) unsigned NOT NULL default '0', +MaxBlobSize smallint(5) unsigned NOT NULL default '0', +MinX smallint(5) unsigned NOT NULL default '0', +MaxX smallint(5) unsigned NOT NULL default '0', +MinY smallint(5) unsigned NOT NULL default '0', +MaxY smallint(5) unsigned NOT NULL default '0', +Score smallint(5) unsigned NOT NULL default '0', +KEY EventId (EventId), +KEY MonitorId (MonitorId), +KEY ZoneId (ZoneId) +) TYPE=MyISAM; +-- Not a problem if this fails +drop table Alarms; diff --git a/db/zm_update-0.9.10.sql b/db/zm_update-0.9.10.sql new file mode 100644 index 000000000..cf8d6f805 --- /dev/null +++ b/db/zm_update-0.9.10.sql @@ -0,0 +1,15 @@ +-- +-- This updates a 0.9.10 database to 0.9.11 +-- +alter table Monitors change column Colours Palette tinyint(3) unsigned NOT NULL default '1'; +update Monitors set Palette = 1 where Palette = 8; +update Monitors set Palette = 4 where Palette = 24; +alter table Zones modify column Type enum('Active','Inclusive','Exclusive','Preclusive','Inactive') not null default 'Active'; +alter table Filters add column AutoArchive tinyint unsigned not null default 0 after Query; +-- These are optional, it just seemed a good time... +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.11.sql b/db/zm_update-0.9.11.sql new file mode 100644 index 000000000..db7ec81e0 --- /dev/null +++ b/db/zm_update-0.9.11.sql @@ -0,0 +1,11 @@ +-- +-- This updates a 0.9.11 database to 0.9.12 +-- +alter table Monitors add column Orientation enum('0','90','180','270') not null default '0' after Palette; +-- These are optional, it just seemed a good time... +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.12.sql b/db/zm_update-0.9.12.sql new file mode 100644 index 000000000..a1f6b3b33 --- /dev/null +++ b/db/zm_update-0.9.12.sql @@ -0,0 +1,26 @@ +-- +-- This updates a 0.9.12 database to 0.9.13 +-- +CREATE TABLE Users ( + Id int(10) unsigned NOT NULL auto_increment, + Username varchar(32) NOT NULL default '', + Password varchar(32) NOT NULL default '', + Enabled tinyint(3) unsigned NOT NULL default '1', + Stream enum('None','View') NOT NULL default 'None', + Events enum('None','View','Edit') NOT NULL default 'None', + Monitors enum('None','View','Edit') NOT NULL default 'None', + System enum('None','View','Edit') NOT NULL default 'None', + MonitorIds tinytext, + PRIMARY KEY (Id), + UNIQUE KEY UC_Id (Id), + UNIQUE KEY UC_Username (Username) +) TYPE=MyISAM; +insert into Users values ('','admin',password('admin'),1,'View','Edit','Edit','Edit',NULL); +-- +-- These are optional, it just seemed a good time... +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.13.sql b/db/zm_update-0.9.13.sql new file mode 100644 index 000000000..932ad5a4c --- /dev/null +++ b/db/zm_update-0.9.13.sql @@ -0,0 +1,28 @@ +-- +-- This updates a 0.9.13 database to 0.9.14 +-- +CREATE TABLE Config ( + Id smallint(5) unsigned NOT NULL default '0', + Name varchar(32) NOT NULL default '', + Value text NOT NULL, + Type tinytext NOT NULL, + DefaultValue tinytext, + Hint tinytext, + Pattern tinytext, + Format tinytext, + Prompt tinytext, + Help text, + Category varchar(32) NOT NULL default '', + Readonly tinyint(3) unsigned NOT NULL default '0', + Requires text, + PRIMARY KEY (Name), + UNIQUE KEY UC_Name (Name) +) TYPE=MyISAM; +-- +-- These are optional, but we might as well +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.15.sql b/db/zm_update-0.9.15.sql new file mode 100644 index 000000000..43538f4ca --- /dev/null +++ b/db/zm_update-0.9.15.sql @@ -0,0 +1,57 @@ +-- +-- This updates a 0.9.15 database to 0.9.16 +-- +-- Make changes to Monitor table +-- +alter table Monitors change column Function OldFunction enum('None','Passive','Active','X10') NOT NULL default 'Passive'; +alter table Monitors add column Function enum('None','Monitor','Modect','Record','Mocord') NOT NULL default 'Monitor'; +alter table Monitors add column RunMode enum('Continuous','Triggered') NOT NULL default 'Continuous' after Function; +alter table Monitors add column Triggers set('X10') NOT NULL after RunMode; +alter table Monitors add column SectionLength int(10) unsigned not null default 600 after PostEventCount; +alter table Monitors add column FrameSkip smallint unsigned not null default 0 after SectionLength; +-- +-- Update to reflect existing setup +-- +update Monitors set Function = 'Monitor' where OldFunction = 'Passive'; +update Monitors set Function = 'Modect' where OldFunction = 'Active'; +update Monitors set Function = 'Modect' where OldFunction = 'X10'; +update Monitors set RunMode = 'Triggered' where OldFunction = 'X10'; +update Monitors set Triggers = 'X10' where OldFunction = 'X10'; +-- +-- Create the X10 triggers table +-- +CREATE TABLE TriggersX10 ( + MonitorId int(10) unsigned NOT NULL default '0', + Activation varchar(32) default NULL, + AlarmInput varchar(32) default NULL, + AlarmOutput varchar(32) default NULL, + PRIMARY KEY (MonitorId) +) TYPE=MyISAM; +-- +-- Update to reflect existing setup +-- +insert into TriggersX10 select Id, X10Activation, X10AlarmInput, X10AlarmOutput from Monitors where Function = 'X10'; +-- +-- Clean up temporary and unused columns +-- +alter table Monitors drop column OldFunction ; +alter table Monitors drop column X10Activation ; +alter table Monitors drop column X10AlarmInput ; +alter table Monitors drop column X10AlarmOutput ; +-- +-- Table structure for table `States` +-- +CREATE TABLE States ( + Name varchar(32) NOT NULL default '', + Definition tinytext NOT NULL, + PRIMARY KEY (Name) +) TYPE=MyISAM; +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.16.sql b/db/zm_update-0.9.16.sql new file mode 100644 index 000000000..f6bb803a9 --- /dev/null +++ b/db/zm_update-0.9.16.sql @@ -0,0 +1,15 @@ +-- +-- This updates a 0.9.16 database to 0.9.17 +-- +-- Make changes to Users table +-- +alter table Users add column Language varchar(8) not null default "" after Password; +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-0.9.7.sql b/db/zm_update-0.9.7.sql new file mode 100644 index 000000000..68f7d5111 --- /dev/null +++ b/db/zm_update-0.9.7.sql @@ -0,0 +1,9 @@ +-- +-- This updates a 0.9.7 database to 0.9.8 +-- +alter table Filters modify column AutoDelete tinyint unsigned not null default 0; +alter table Filters modify column AutoUpload tinyint unsigned not null default 0; +alter table Filters add column AutoEmail tinyint unsigned not null default 0; +alter table Filters add column AutoMessage tinyint unsigned not null default 0; +alter table Events add column Emailed tinyint unsigned not null default 0 after Uploaded; +alter table Events add column Messaged tinyint unsigned not null default 0 after Emailed; diff --git a/db/zm_update-0.9.8.sql b/db/zm_update-0.9.8.sql new file mode 100644 index 000000000..9176c0296 --- /dev/null +++ b/db/zm_update-0.9.8.sql @@ -0,0 +1,8 @@ +-- +-- This updates a 0.9.8 database to 0.9.9 +-- +update Monitors set Colours = Colours * 8; +optimize table Events; +alter table Events modify column Length numeric( 10, 2 ) not null default 0.00; +optimize table Frames; +alter table Frames add column Delta numeric( 8, 2 ) not null default 0.00 after TimeStamp; diff --git a/db/zm_update-0.9.9.sql b/db/zm_update-0.9.9.sql new file mode 100644 index 000000000..77d2d9c27 --- /dev/null +++ b/db/zm_update-0.9.9.sql @@ -0,0 +1,15 @@ +-- +-- This updates a 0.9.9 database to 0.9.10 +-- +alter table Monitors add column Type enum('Local','Remote') NOT NULL default 'Local' after Name; +alter table Monitors add column Host varchar(64) default NULL after Format; +alter table Monitors add column Port varchar(8) default '80' after Host; +alter table Monitors add column Path varchar(255) default NULL after Port; +alter table Monitors add column MaxFPS decimal( 5, 2) not null default 0.0 after AlarmFrameCount; +alter table Monitors drop column AlarmFrameCount; +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.17.1.sql b/db/zm_update-1.17.1.sql new file mode 100644 index 000000000..bcedd219a --- /dev/null +++ b/db/zm_update-1.17.1.sql @@ -0,0 +1,17 @@ +-- +-- This updates a 1.17.1 database to 1.17.2 +-- +-- Make changes to Zones table +-- +alter table Zones change column AlarmThreshold MinPixelThreshold smallint unsigned; +alter table Zones add column MaxPixelThreshold smallint unsigned after MinPixelThreshold; +alter table Events drop column ImagePath; +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.17.2.sql b/db/zm_update-1.17.2.sql new file mode 100644 index 000000000..15197bdf5 --- /dev/null +++ b/db/zm_update-1.17.2.sql @@ -0,0 +1,18 @@ +-- +-- This updates a 1.17.2 database to 1.18.0 +-- +-- Make changes to Filter table +-- +alter table Zones add column CheckMethod enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs' after AlarmRGB; +alter table Filters drop index FilterIDX; +alter table Filters drop column MonitorId; +update Filters set AutoArchive = 0, AutoDelete = 0, AutoUpload = 0, AutoEmail = 0, AutoMessage = 0; +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.18.0.sql b/db/zm_update-1.18.0.sql new file mode 100644 index 000000000..9bd6b37c9 --- /dev/null +++ b/db/zm_update-1.18.0.sql @@ -0,0 +1,3 @@ +-- +-- There are no updates from a 1.18.0 database to 1.18.1 +-- diff --git a/db/zm_update-1.18.1.sql b/db/zm_update-1.18.1.sql new file mode 100644 index 000000000..febfcd87e --- /dev/null +++ b/db/zm_update-1.18.1.sql @@ -0,0 +1,22 @@ +-- +-- This updates a 1.18.1 database to 1.19.0 +-- +-- Make changes to Frames table +-- +alter table Frames add column Type enum('Normal','Bulk','Alarm') NOT NULL default 'Normal' after FrameId; +update Frames set Type = 'Alarm' where AlarmFrame = 1; +alter table Frames drop column AlarmFrame; +-- +-- Make changes to Filters table +update Filters set Name = concat( Name, '_', Id ); +alter table Filters drop column Id; +alter table Filters add primary key(Name); +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.19.0.sql b/db/zm_update-1.19.0.sql new file mode 100644 index 000000000..7eddc1531 --- /dev/null +++ b/db/zm_update-1.19.0.sql @@ -0,0 +1,3 @@ +-- +-- There are no updates from a 1.19.0 database to 1.19.1 +-- diff --git a/db/zm_update-1.19.1.sql b/db/zm_update-1.19.1.sql new file mode 100644 index 000000000..6cdc7dd4c --- /dev/null +++ b/db/zm_update-1.19.1.sql @@ -0,0 +1,23 @@ +-- +-- This updates a 1.19.1 database to 1.19.2 +-- +-- Make changes to Events table +-- +alter table Events add column Executed tinyint(3) unsigned not null default 0 after Messaged; +-- +-- Make changes to Filters table +-- +alter table Filters add column AutoExecute tinytext default ''; +-- +-- Add in a sample filter to purge the oldest 5 events when the disk is 99% full, delete is disabled though +-- +insert into Filters values ('PurgeWhenFull','trms=2&obr1=&cbr1=&attr1=Archived&op1=&val1=0&cnj2=and&obr2=&cbr2=&attr2=DiskPercent&op2=>=&val2=99&sort_field=Id&sort_asc=1&limit=5',0,0,0,0,0,''); +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.19.2.sql b/db/zm_update-1.19.2.sql new file mode 100644 index 000000000..03e5c5316 --- /dev/null +++ b/db/zm_update-1.19.2.sql @@ -0,0 +1,15 @@ +-- +-- This updates a 1.19.2 database to 1.19.3 +-- +-- Make changes to Users table +-- +alter table Users modify column Password varchar(64) not null default ''; +-- +-- These are optional, but we might as well +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.19.3.sql b/db/zm_update-1.19.3.sql new file mode 100644 index 000000000..10ff33f19 --- /dev/null +++ b/db/zm_update-1.19.3.sql @@ -0,0 +1,3 @@ +-- +-- There are no updates from a 1.19.3 database to 1.19.4 +-- diff --git a/db/zm_update-1.19.4.sql b/db/zm_update-1.19.4.sql new file mode 100644 index 000000000..1085e82f3 --- /dev/null +++ b/db/zm_update-1.19.4.sql @@ -0,0 +1,20 @@ +-- +-- This updates a 1.19.4 database to 1.19.5 +-- +-- Make changes to Monitors table +-- +alter table Monitors add column EventPrefix varchar(32) not null default 'Event-' after Orientation; +alter table Monitors add column AlarmFrameCount smallint(5) unsigned not null default '1' after PostEventCount; +alter table Monitors add column Brightness mediumint(7) NOT NULL default '-1' after Orientation; +alter table Monitors add column Contrast mediumint(7) NOT NULL default '-1' after Brightness; +alter table Monitors add column Hue mediumint(7) NOT NULL default '-1' after Contrast; +alter table Monitors add column Colour mediumint(7) NOT NULL default '-1' after Hue; +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.19.5.sql b/db/zm_update-1.19.5.sql new file mode 100644 index 000000000..bb2f27aa1 --- /dev/null +++ b/db/zm_update-1.19.5.sql @@ -0,0 +1,44 @@ +-- +-- This updates a 1.19.5 database to 1.20.0 +-- +-- Create the Groups table +-- +CREATE TABLE Groups ( + Id int(10) unsigned NOT NULL auto_increment, + Name varchar(64) NOT NULL, + MonitorIds tinytext NOT NULL, + PRIMARY KEY (Id) +) TYPE=MyISAM; +-- +-- Make changes to Users table +-- +alter table Users modify MonitorIds tinytext not null default ''; +-- +-- Make changes to Monitors table +-- +alter table Monitors modify column Function enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor'; +-- +-- Make changes to Events table +-- +alter table Events add column Cause varchar(32) not null default '' after Name; +alter table Events add column Notes tinytext after LearnState; +-- +-- Add a new index to the Events table +-- +alter table Events add index (Frames); +-- +-- Rationalise some of the name columns +alter table Events modify column Name varchar(64) not null; +alter table Filters modify column Name varchar(64) not null; +alter table Monitors modify column Name varchar(64) not null; +alter table States modify column Name varchar(64) not null; +alter table Zones modify column Name varchar(64) not null; +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.20.0.sql b/db/zm_update-1.20.0.sql new file mode 100644 index 000000000..de5e10ac3 --- /dev/null +++ b/db/zm_update-1.20.0.sql @@ -0,0 +1,15 @@ +-- +-- This updates a 1.20.0 database to 1.20.1 +-- +-- Make changes to Users table +-- +alter table Users modify column Username varchar(32) BINARY NOT NULL default ''; +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.20.1.sql b/db/zm_update-1.20.1.sql new file mode 100644 index 000000000..2449ba664 --- /dev/null +++ b/db/zm_update-1.20.1.sql @@ -0,0 +1,148 @@ +-- +-- This updates a 1.20.0 database to 1.20.1 +-- +-- Make changes to Monitors table +-- +alter table Monitors add column Controllable tinyint(3) unsigned NOT NULL default '0'; +alter table Monitors add column ControlId int(10) unsigned NOT NULL default '0'; +alter table Monitors add column ControlDevice varchar(255) default NULL; +alter table Monitors add column ControlAddress varchar(255) default NULL; +alter table Monitors add column TrackMotion tinyint(3) unsigned NOT NULL default '0'; +alter table Monitors add column TrackDelay smallint(5) unsigned NOT NULL default '0'; +alter table Monitors add column ReturnLocation tinyint(3) NOT NULL default '-1'; +alter table Monitors add column ReturnDelay smallint(5) unsigned NOT NULL default '0'; + +-- +-- Add new table `Controls` +-- +CREATE TABLE Controls ( + Id int(10) unsigned NOT NULL auto_increment, + Name varchar(64) NOT NULL default '', + Type enum('Local','Remote') NOT NULL default 'Local', + Command varchar(255) default NULL, + + CanWake tinyint(3) unsigned NOT NULL default '0', + CanSleep tinyint(3) unsigned NOT NULL default '0', + CanReset tinyint(3) unsigned NOT NULL default '0', + + CanZoom tinyint(3) unsigned NOT NULL default '0', + CanAutoZoom tinyint(3) unsigned NOT NULL default '0', + CanZoomAbs tinyint(3) unsigned NOT NULL default '0', + CanZoomRel tinyint(3) unsigned NOT NULL default '0', + CanZoomCon tinyint(3) unsigned NOT NULL default '0', + MinZoomRange int(10) unsigned default NULL, + MaxZoomRange int(10) unsigned default NULL, + MinZoomStep int(10) unsigned default NULL, + MaxZoomStep int(10) unsigned default NULL, + HasZoomSpeed tinyint(3) unsigned NOT NULL default '0', + MinZoomSpeed int(10) unsigned default NULL, + MaxZoomSpeed int(10) unsigned default NULL, + + CanFocus tinyint(3) unsigned NOT NULL default '0', + CanAutoFocus tinyint(3) unsigned NOT NULL default '0', + CanFocusAbs tinyint(3) unsigned NOT NULL default '0', + CanFocusRel tinyint(3) unsigned NOT NULL default '0', + CanFocusCon tinyint(3) unsigned NOT NULL default '0', + MinFocusRange int(10) unsigned default NULL, + MaxFocusRange int(10) unsigned default NULL, + MinFocusStep int(10) unsigned default NULL, + MaxFocusStep int(10) unsigned default NULL, + HasFocusSpeed tinyint(3) unsigned NOT NULL default '0', + MinFocusSpeed int(10) unsigned default NULL, + MaxFocusSpeed int(10) unsigned default NULL, + + CanIris tinyint(3) unsigned NOT NULL default '0', + CanAutoIris tinyint(3) unsigned NOT NULL default '0', + CanIrisAbs tinyint(3) unsigned NOT NULL default '0', + CanIrisRel tinyint(3) unsigned NOT NULL default '0', + CanIrisCon tinyint(3) unsigned NOT NULL default '0', + MinIrisRange int(10) unsigned default NULL, + MaxIrisRange int(10) unsigned default NULL, + MinIrisStep int(10) unsigned default NULL, + MaxIrisStep int(10) unsigned default NULL, + HasIrisSpeed tinyint(3) unsigned NOT NULL default '0', + MinIrisSpeed int(10) unsigned default NULL, + MaxIrisSpeed int(10) unsigned default NULL, + + CanGain tinyint(3) unsigned NOT NULL default '0', + CanAutoGain tinyint(3) unsigned NOT NULL default '0', + CanGainAbs tinyint(3) unsigned NOT NULL default '0', + CanGainRel tinyint(3) unsigned NOT NULL default '0', + CanGainCon tinyint(3) unsigned NOT NULL default '0', + MinGainRange int(10) unsigned default NULL, + MaxGainRange int(10) unsigned default NULL, + MinGainStep int(10) unsigned default NULL, + MaxGainStep int(10) unsigned default NULL, + HasGainSpeed tinyint(3) unsigned NOT NULL default '0', + MinGainSpeed int(10) unsigned default NULL, + MaxGainSpeed int(10) unsigned default NULL, + + CanWhite tinyint(3) unsigned NOT NULL default '0', + CanAutoWhite tinyint(3) unsigned NOT NULL default '0', + CanWhiteAbs tinyint(3) unsigned NOT NULL default '0', + CanWhiteRel tinyint(3) unsigned NOT NULL default '0', + CanWhiteCon tinyint(3) unsigned NOT NULL default '0', + MinWhiteRange int(10) unsigned default NULL, + MaxWhiteRange int(10) unsigned default NULL, + MinWhiteStep int(10) unsigned default NULL, + MaxWhiteStep int(10) unsigned default NULL, + HasWhiteSpeed tinyint(3) unsigned NOT NULL default '0', + MinWhiteSpeed int(10) unsigned default NULL, + MaxWhiteSpeed int(10) unsigned default NULL, + + HasPresets tinyint(3) unsigned NOT NULL default '0', + NumPresets tinyint(3) unsigned NOT NULL default '0', + HasHomePreset tinyint(3) unsigned NOT NULL default '0', + CanSetPresets tinyint(3) unsigned NOT NULL default '0', + + CanMove tinyint(3) unsigned NOT NULL default '0', + CanMoveDiag tinyint(3) unsigned NOT NULL default '0', + CanMoveMap tinyint(3) unsigned NOT NULL default '0', + CanMoveAbs tinyint(3) unsigned NOT NULL default '0', + CanMoveRel tinyint(3) unsigned NOT NULL default '0', + CanMoveCon tinyint(3) unsigned NOT NULL default '0', + CanPan tinyint(3) unsigned NOT NULL default '0', + MinPanRange int(10) default NULL, + MaxPanRange int(10) default NULL, + MinPanStep int(10) default NULL, + MaxPanStep int(10) default NULL, + HasPanSpeed tinyint(3) unsigned NOT NULL default '0', + MinPanSpeed int(10) default NULL, + MaxPanSpeed int(10) default NULL, + HasTurboPan tinyint(3) unsigned NOT NULL default '0', + TurboPanSpeed int(10) default NULL, + CanTilt tinyint(3) unsigned NOT NULL default '0', + MinTiltRange int(10) default NULL, + MaxTiltRange int(10) default NULL, + MinTiltStep int(10) default NULL, + MaxTiltStep int(10) default NULL, + HasTiltSpeed tinyint(3) unsigned NOT NULL default '0', + MinTiltSpeed int(10) default NULL, + MaxTiltSpeed int(10) default NULL, + HasTurboTilt tinyint(3) unsigned NOT NULL default '0', + TurboTiltSpeed int(10) default NULL, + + CanAutoScan tinyint(3) unsigned NOT NULL default '0', + NumScanPaths tinyint(3) unsigned NOT NULL default '0', + + PRIMARY KEY (Id), + UNIQUE KEY UC_Id (Id) +) TYPE=MyISAM; + +-- +-- Some sample control protocol definitions +-- +insert into Controls values (1,'pelco-d','Local','/usr/local/bin/zmcontrol-pelco-d.pl',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +insert into Controls values (2,'visca','Local','/usr/local/bin/zmcontrol-visca.pl',1,1,0,1,0,0,0,1,0,16384,10,4000,1,1,6,1,1,1,0,1,0,1536,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,3,1,1,1,1,0,1,1,0,1,-15578,15578,100,10000,1,1,50,1,254,1,-7789,7789,100,5000,1,1,50,1,254,0,0); +insert into Controls values (3,'KX-HCM10','Remote','/usr/local/bin/zmcontrol-kx-hcm10.pl',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,8,1,1,1,0,1,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); +insert into Controls values (4,'pelco-d-full','Local','/usr/local/bin/zmcontrol-pelco-d.pl',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.21.0.sql b/db/zm_update-1.21.0.sql new file mode 100644 index 000000000..4ef18e511 --- /dev/null +++ b/db/zm_update-1.21.0.sql @@ -0,0 +1,31 @@ +-- +-- This updates a 1.21.0 database to 1.21.1 +-- +-- Make changes to Monitors table +-- +alter table Monitors modify column Orientation enum('0','90','180','270','hori','vert') NOT NULL default '0'; +alter table Monitors add column AutoStopTimeout decimal(5,2) default NULL after ControlAddress; +-- +-- Make changes to Stats table +-- +alter table Stats modify column MinBlobSize int(10) unsigned NOT NULL default '0'; +alter table Stats modify column MaxBlobSize int(10) unsigned NOT NULL default '0'; +-- +-- Make changes to Zones table +-- +alter table Zones modify column MinBlobPixels int(10) unsigned default NULL; +alter table Zones modify column MaxBlobPixels int(10) unsigned default NULL; +-- +-- Add in extra PTZ protocol +-- +insert into Controls values (0,'PELCO-P','Local','/usr/local/bin/zmcontrol-pelco-p.pl',1,1,0,1,1,0,0,1,NULL,NULL,NULL,NULL,1,0,3,1,1,0,0,1,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,1,0,1,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,20,1,1,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,1,0,63,1,254,1,NULL,NULL,NULL,NULL,1,0,63,1,254,0,0); +INSERT INTO Controls VALUES (0,'Axis API v2','Remote','/usr/local/bin/zmcontrol-axis-v2.pl',0,0,0,1,0,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,1,1,0,1,0,0,9999,10,2500,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,12,1,1,1,1,1,0,1,0,1,-360,360,1,90,0,NULL,NULL,0,NULL,1,-360,360,1,90,0,NULL,NULL,0,NULL,0,0); +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.21.1.sql b/db/zm_update-1.21.1.sql new file mode 100644 index 000000000..aedfe7d29 --- /dev/null +++ b/db/zm_update-1.21.1.sql @@ -0,0 +1,13 @@ +-- +-- This updates a 1.21.1 database to 1.21.2 +-- +-- No changes required +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.21.2.sql b/db/zm_update-1.21.2.sql new file mode 100644 index 000000000..c47aa54cf --- /dev/null +++ b/db/zm_update-1.21.2.sql @@ -0,0 +1,13 @@ +-- +-- This updates a 1.21.2 database to 1.21.3 +-- +-- No changes required +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.21.3.sql b/db/zm_update-1.21.3.sql new file mode 100644 index 000000000..0ecf4b862 --- /dev/null +++ b/db/zm_update-1.21.3.sql @@ -0,0 +1,25 @@ +-- +-- This updates a 1.21.3 database to 1.21.4 +-- +alter table Monitors add column WebColour varchar(32) not null default 'red'; +update Monitors set WebColour = concat( '#', hex(14*rand()),hex(15*rand()),hex(14*rand()),hex(15*rand()),hex(14*rand()),hex(15*rand()) ); +alter table Monitors add column Sequence smallint unsigned; +alter table Monitors modify column Device tinytext; +update Monitors set Device = concat( "/dev/video", Device ); +update Monitors set Device = NULL where Type = "Remote"; +alter table Monitors add column DefaultScale smallint unsigned after ReturnDelay; +alter table Monitors modify column Type enum('Local','Remote','File') NOT NULL default 'Local'; +alter table Events add column Height smallint(5) unsigned not null default '0' after EndTime; +alter table Events add column Width smallint(5) unsigned not null default '0' after EndTime; +alter table Users add column Control enum('None','View','Edit') NOT NULL default 'None' after Events; +update Users set Control = System; +alter table Users add column MaxBandwidth varchar(16) not null default '' after System; +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.21.4.sql b/db/zm_update-1.21.4.sql new file mode 100644 index 000000000..3fd2444f3 --- /dev/null +++ b/db/zm_update-1.21.4.sql @@ -0,0 +1,134 @@ +-- +-- This updates a 1.21.4 database to 1.22.0 +-- +alter table Monitors change column RunMode Enabled tinyint(3) unsigned NOT NULL default '1'; +alter table Monitors add column DefaultRate smallint unsigned not null default 100 after ReturnDelay; +-- +alter table Events add column Videoed tinyint unsigned not null default 0 after Archived; +alter table Filters add column AutoVideo tinyint unsigned not null default 0 after AutoArchive; +alter table Filters add column Temp tinyint unsigned not null default 0; +update Filters set Temp = AutoDelete; +alter table Filters drop column AutoDelete; +alter table Filters change column Temp AutoDelete tinyint unsigned not null default 0; +alter table Filters change column AutoExecute AutoExecuteCmd tinytext; +alter table Filters add column AutoExecute tinyint unsigned not null default 0 after AutoMessage; +update Filters set AutoExecute = if(isnull(AutoExecuteCmd)||AutoExecuteCmd='', 0, 1 ); +-- +alter table Zones add column NumCoords tinyint(3) unsigned NOT NULL default '0' after Units; +alter table Zones add column Coords tinytext NOT NULL after NumCoords; +alter table Zones add column Area int(10) unsigned not null default 0 after Coords; +alter table Zones modify column AlarmRGB int(10) unsigned default '0'; +alter table Zones add index MonitorId (MonitorId); +-- +insert into Controls values ('','Neu-Fusion NCS370','Remote','zmcontrol-ncs370.pl',0,0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,0,NULL,NULL,1,24,1,0,1,1,0,0,0,1,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,1,NULL,NULL,NULL,NULL,0,NULL,NULL,0,NULL,0,0); + +-- +-- Table structure for table `MonitorPresets` +-- +CREATE TABLE MonitorPresets ( + Id int(10) unsigned NOT NULL auto_increment, + Name varchar(64) NOT NULL, + Type enum('Local','Remote','File') NOT NULL default 'Local', + Device tinytext, + Channel varchar(32) default NULL, + Format varchar(32) default NULL, + Host varchar(64) default NULL, + Port varchar(8) default NULL, + Path varchar(255) default NULL, + Width smallint(5) unsigned default NULL, + Height smallint(5) unsigned default NULL, + Palette tinyint(3) unsigned default NULL, + MaxFPS decimal(5,2) default NULL, + Controllable tinyint(3) unsigned NOT NULL default '0', + ControlId varchar(16) default NULL, + ControlDevice varchar(255) default NULL, + ControlAddress varchar(255) default NULL, + DefaultRate smallint(5) unsigned NOT NULL default '100', + DefaultScale smallint(5) unsigned NOT NULL default '100', + PRIMARY KEY (Id) +) TYPE=MyISAM; + +-- +-- Dumping data for table `MonitorPresets` +-- +INSERT INTO MonitorPresets VALUES ('','BTTV Video, PAL, 320x240','Local','/dev/video','','0',NULL,NULL,NULL,320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, PAL, 320x240, max 5 FPS','Local','/dev/video','','0',NULL,NULL,NULL,320,240,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, PAL, 640x480','Local','/dev/video','','0',NULL,NULL,NULL,640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, PAL, 640x480, max 5 FPS','Local','/dev/video','','0',NULL,NULL,NULL,640,480,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, NTSC, 320x240','Local','/dev/video','','1',NULL,NULL,NULL,320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, NTSC, 320x240, max 5 FPS','Local','/dev/video','','1',NULL,NULL,NULL,320,240,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, NTSC, 640x480','Local','/dev/video','','1',NULL,NULL,NULL,640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video, NTSC, 640x480, max 5 FPS','Local','/dev/video','','1',NULL,NULL,NULL,640,480,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',320,240,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',640,480,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240',320,240,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, mpjpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&req_fps=5',320,240,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',320,240,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 320x240, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=320x240',320,240,4,5.0,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480',640,480,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, mpjpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&req_fps=5',640,480,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',640,480,4,NULL,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP PTZ, 640x480, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/jpg/image.cgi?resolution=640x480',640,480,4,5.0,1,4,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 320x240, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',320,240,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP, 640x480, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',640,480,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',320,240,4,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',320,240,4,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 320x240, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',320,240,4,5.0,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/nphMotionJpeg?Resolution=640x480&Quality=Standard',640,480,4,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',640,480,4,NULL,1,5,NULL,':',100,100); +INSERT INTO MonitorPresets VALUES ('','Panasonic IP PTZ, 640x480, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/SnapshotJPEG?Resolution=640x480&Quality=Standard',640,480,4,5.0,1,5,NULL,':',100,100); + +-- +-- Table structure for table `ZonePresets` +-- +CREATE TABLE ZonePresets ( + Id int(10) unsigned NOT NULL auto_increment, + Name varchar(64) NOT NULL default '', + Type enum('Active','Inclusive','Exclusive','Preclusive','Inactive') NOT NULL default 'Active', + Units enum('Pixels','Percent') NOT NULL default 'Pixels', + CheckMethod enum('AlarmedPixels','FilteredPixels','Blobs') NOT NULL default 'Blobs', + MinPixelThreshold smallint(5) unsigned default NULL, + MaxPixelThreshold smallint(5) unsigned default NULL, + MinAlarmPixels int(10) unsigned default NULL, + MaxAlarmPixels int(10) unsigned default NULL, + FilterX tinyint(3) unsigned default NULL, + FilterY tinyint(3) unsigned default NULL, + MinFilterPixels int(10) unsigned default NULL, + MaxFilterPixels int(10) unsigned default NULL, + MinBlobPixels int(10) unsigned default NULL, + MaxBlobPixels int(10) unsigned default NULL, + MinBlobs smallint(5) unsigned default NULL, + MaxBlobs smallint(5) unsigned default NULL, + PRIMARY KEY (Id), + UNIQUE KEY UC_Id (Id) +) TYPE=MyISAM; + +-- +-- Dumping data for table `ZonePresets` +-- +INSERT INTO ZonePresets VALUES (1,'Fast, low sensitivity','Active','Percent','AlarmedPixels',25,NULL,20,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO ZonePresets VALUES (2,'Fast, medium sensitivity','Active','Percent','AlarmedPixels',15,NULL,10,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO ZonePresets VALUES (3,'Fast, high sensitivity','Active','Percent','AlarmedPixels',10,NULL,5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +INSERT INTO ZonePresets VALUES (4,'Best, low sensitivity','Active','Percent','Blobs',25,NULL,36,NULL,7,7,24,NULL,20,NULL,1,NULL); +INSERT INTO ZonePresets VALUES (5,'Best, medium sensitivity','Active','Percent','Blobs',15,NULL,16,NULL,5,5,12,NULL,10,NULL,1,NULL); +INSERT INTO ZonePresets VALUES (6,'Best, high sensitivity','Active','Percent','Blobs',10,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.22.0.sql b/db/zm_update-1.22.0.sql new file mode 100644 index 000000000..30bf17066 --- /dev/null +++ b/db/zm_update-1.22.0.sql @@ -0,0 +1,56 @@ +-- +-- This updates a 1.22.0 database to 1.22.1 +-- + +-- +-- Add support for linked monitors +-- +alter table Monitors add column LinkedMonitors varchar(255) NOT NULL default '' after Enabled; + +-- +-- Revise some defaults and sizes +-- +alter table Monitors modify column Device varchar(64) not null default ''; +alter table Monitors modify column Host varchar(64) not null default ''; +alter table Monitors modify column Port varchar(8) not null default ''; +alter table Monitors modify column Path varchar(255) not null default ''; +alter table Monitors modify column LabelX smallint(5) unsigned not null default 0; +alter table Monitors modify column LabelY smallint(5) unsigned not null default 0; +alter table Monitors modify column MaxFPS decimal(5,2) default NULL; +update Monitors set MaxFPS = NULL where MaxFPS = 0.00; + +-- +-- Add monitor specific alarm max FPS +-- +alter table Monitors add column AlarmMaxFPS decimal(5,2) default NULL after MaxFPS; + +-- +-- Add average pixel difference to stats +-- +alter table Stats add column PixelDiff tinyint(3) unsigned NOT NULL default '0' after FrameId; + +-- +-- Add some new monitor presets +-- +INSERT INTO MonitorPresets VALUES ('','Axis IP, 320x240, mpjpeg, B&W','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=320x240&color=0',320,240,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Axis IP, 640x480, mpjpeg, B&W','Remote',NULL,NULL,NULL,'',80,'/axis-cgi/mjpg/video.cgi?resolution=640x480&color=0',640,480,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, jpeg, max 5 FPS','Remote',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,4,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/GetData.cgi',NULL,NULL,4,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','Gadspot IP, mpjpeg','Remote',NULL,NULL,NULL,'',80,'/Jpeg/CamImg.jpg',NULL,NULL,4,5.0,0,NULL,NULL,NULL,100,100); + +-- +-- Modify zone presets a bit +-- +UPDATE ZonePresets SET MinPixelThreshold = 60 WHERE Id = 1 OR Id = 4; +UPDATE ZonePresets SET MinPixelThreshold = 40 WHERE Id = 2 OR Id = 5; +UPDATE ZonePresets SET MinPixelThreshold = 20 WHERE Id = 3 OR Id = 6; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.22.1.sql b/db/zm_update-1.22.1.sql new file mode 100644 index 000000000..86429c561 --- /dev/null +++ b/db/zm_update-1.22.1.sql @@ -0,0 +1,26 @@ +-- +-- This updates a 1.22.1 database to 1.22.2 +-- + +-- +-- Add missing Zone Preset +-- +replace into ZonePresets values (6,'Best, high sensitivity','Active','Percent','Blobs',20,NULL,8,NULL,3,3,6,NULL,5,NULL,1,NULL); + +-- +-- Remove redundant Zone columns +-- +alter table Zones drop column LoX; +alter table Zones drop column HiX; +alter table Zones drop column LoY; +alter table Zones drop column HiY; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.22.2.sql b/db/zm_update-1.22.2.sql new file mode 100644 index 000000000..dcc8523dd --- /dev/null +++ b/db/zm_update-1.22.2.sql @@ -0,0 +1,63 @@ +-- +-- This updates a 1.22.2 database to 1.22.3 +-- + +-- +-- Add new Background column into Filters +-- +alter table Filters add column Background tinyint(1) unsigned not null default 0; + +-- +-- Set the Background flag for any filters currently saved with Auto tasks +-- +update Filters set Background = 1 where (AutoArchive = 1 or AutoVideo = 1 or AutoUpload = 1 or AutoEmail = 1 or AutoMessage = 1 or AutoExecute = 1 or AutoDelete = 1); + +-- +-- Add default view column into Monitors +-- +alter table Monitors add column DefaultView enum ('Events','Control') not null default 'Events' after ReturnDelay; +alter table Monitors modify LabelFormat varchar(64) NOT NULL default '%%s - %y/%m/%d %H:%M:%S'; + +-- +-- Add device permissions column into Users, set the permissions for existing users to +-- be the same as for Monitors as a default +-- +alter table Users add column Devices enum('None','View','Edit') NOT NULL default 'None' after Monitors; +update Users set Devices = Monitors; + +-- +-- Increase size of Notes field in Events +-- +alter table Events modify column Notes text; + +-- +-- Create new preset labels table +-- +CREATE TABLE `ControlPresets` ( + `MonitorId` int(10) unsigned NOT NULL default '0', + `Preset` int(10) unsigned NOT NULL default '0', + `Label` varchar(64) NOT NULL default '', + PRIMARY KEY (`MonitorId`,`Preset`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- +-- Create new devices table +-- +CREATE TABLE `Devices` ( + `Id` int(10) unsigned NOT NULL auto_increment, + `Name` tinytext NOT NULL, + `Type` enum('X10') NOT NULL default 'X10', + `KeyString` varchar(32) NOT NULL default '', + PRIMARY KEY (`Id`), + UNIQUE KEY `UC_Id` (`Id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.22.3.sql b/db/zm_update-1.22.3.sql new file mode 100644 index 000000000..d86b4d021 --- /dev/null +++ b/db/zm_update-1.22.3.sql @@ -0,0 +1,70 @@ +-- +-- This updates a 1.22.3 database to 1.23.0 +-- + +-- +-- Add a column for buffer replay streams +-- +alter table Monitors add column `StreamReplayBuffer` int(10) unsigned NOT NULL default '1000' after PostEventCount; + +-- +-- Change the default timestamp format +-- +alter table Monitors modify column `LabelFormat` varchar(64) NOT NULL default '%N - %y/%m/%d %H:%M:%S'; + +-- +-- Add a column for signal check colour +-- +alter table Monitors add column `SignalCheckColour` varchar(32) NOT NULL default '#0100BE' after DefaultScale; + +-- +-- Increase the size of the run state definition column +-- +alter table States modify column Definition text; + +-- +-- Add overload shutout to zones and presets +-- +alter table Zones add column OverloadFrames smallint(5) unsigned NOT NULL default '0' after MaxBlobs; +alter table ZonePresets add column OverloadFrames smallint(5) unsigned NOT NULL default '0' after MaxBlobs; + +-- +-- Change control command to protocol module +-- +alter table Controls add column Protocol varchar(32) after Command; +update Controls set Protocol = "PelcoD" where Command like "%zmcontrol-pelco-d.pl"; +update Controls set Protocol = "PelcoP" where Command like "%zmcontrol-pelco-p.pl"; +update Controls set Protocol = "Visca" where Command like "%zmcontrol-visca.pl"; +update Controls set Protocol = "PanasonicIP" where Command like "%zmcontrol-panasonic-ip.pl"; +update Controls set Protocol = "AxisV2" where Command like "%zmcontrol-axis-v2.pl"; +update Controls set Protocol = "Ncs370" where Command like "%zmcontrol-ncs370.pl"; +update Controls set Protocol = "VclTP" where Command like "%zmcontrol-vcltp.pl"; +alter table Controls drop column Command; + +-- +-- Drop some duplicate/redundant indices +-- +alter table Config drop index `UC_Name`; +alter table Controls drop index `UC_Id`; +alter table Devices drop index `UC_Id`; +alter table Events drop index `UC_Id`; +alter table Frames drop index `UC_Id`; +alter table Users drop index `UC_Id`; +alter table ZonePresets drop index `UC_Id`; +alter table Zones drop index `UC_Id`; +alter table Events drop primary key; +alter table Events add primary key ( `Id`, `MonitorId` ); +alter table Events drop index `Id`; +alter table Frames drop column `Id`; +alter table Frames drop index `EventId`; +alter table Frames add primary key ( `EventId`, `FrameId` ); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.23.0.sql b/db/zm_update-1.23.0.sql new file mode 100644 index 000000000..d521e2f09 --- /dev/null +++ b/db/zm_update-1.23.0.sql @@ -0,0 +1,18 @@ +-- +-- This updates a 1.23.0 database to 1.23.1 +-- + +-- +-- Change protocol field slightly +-- +alter table Controls modify Protocol varchar(64); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.23.1.sql b/db/zm_update-1.23.1.sql new file mode 100644 index 000000000..bc0c4fa28 --- /dev/null +++ b/db/zm_update-1.23.1.sql @@ -0,0 +1,19 @@ +-- +-- This updates a 1.23.1 database to 1.23.2 +-- + +-- +-- Rename and fix typo version of PurgeWhenFull +-- +update Filters set Name = "PurgeWhenFull" where Name = "xPurgeWhenFull"; +update Filters set Query = 'a:4:{s:5:"terms";a:2:{i:0;a:3:{s:3:"val";s:1:"0";s:4:"attr";s:8:"Archived";s:2:"op";s:1:"=";}i:1;a:4:{s:3:"cnj";s:3:"and";s:3:"val";s:2:"95";s:4:"attr";s:11:"DiskPercent";s:2:"op";s:2:">=";}}s:10:"sort_field";s:2:"Id";s:8:"sort_asc";s:1:"1";s:5:"limit";s:2:"5";}' where Name = "PurgeWhenFull" and Query like "trms=%"; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.23.2.sql b/db/zm_update-1.23.2.sql new file mode 100644 index 000000000..3897a4dda --- /dev/null +++ b/db/zm_update-1.23.2.sql @@ -0,0 +1,18 @@ +-- +-- This updates a 1.23.2 database to 1.23.3 +-- + +-- +-- Rename and fix typo version of PurgeWhenFull +-- +update Filters set Query = 'a:4:{s:5:"terms";a:2:{i:0;a:3:{s:3:"val";s:1:"0";s:4:"attr";s:8:"Archived";s:2:"op";s:1:"=";}i:1;a:4:{s:3:"cnj";s:3:"and";s:3:"val";s:2:"95";s:4:"attr";s:11:"DiskPercent";s:2:"op";s:2:">=";}}s:10:"sort_field";s:2:"Id";s:8:"sort_asc";s:1:"1";s:5:"limit";s:1:"5";}' where Name = "PurgeWhenFull" and Query = 'a:4:{s:5:"terms";a:2:{i:0;a:3:{s:3:"val";s:1:"0";s:4:"attr";s:8:"Archived";s:2:"op";s:1:"=";}i:1;a:4:{s:3:"cnj";s:3:"and";s:3:"val";s:2:"95";s:4:"attr";s:11:"DiskPercent";s:2:"op";s:2:">=";}}s:10:"sort_field";s:2:"Id";s:8:"sort_asc";s:1:"1";s:5:"limit";s:2:"5";}'; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.23.3.sql b/db/zm_update-1.23.3.sql new file mode 100644 index 000000000..5c1757fca --- /dev/null +++ b/db/zm_update-1.23.3.sql @@ -0,0 +1,83 @@ +-- +-- This updates a 1.23.3 database to 1.24.0 +-- + +-- +-- Add protocol column for monitors +-- +alter table Monitors add column `Protocol` varchar(16) not null default '' after `Format`; +alter table MonitorPresets add column `Protocol` varchar(16) default NULL after `Format`; +update Monitors set Protocol = "http" where Type = "Remote"; +update MonitorPresets set Protocol = "http" where Type = "Remote"; + +-- +-- Add method column for monitors; +-- +alter table Monitors add column `Method` varchar(16) not null default '' after `Protocol`; +alter table MonitorPresets add column `Method` varchar(16) default NULL after `Protocol`; +update Monitors set Method = "simple" where Type = "Remote" and ( select Value from Config where Name = "ZM_NETCAM_REGEXPS" ) = 0; +update Monitors set Method = "regexp" where Type = "Remote" and ( select Value from Config where Name = "ZM_NETCAM_REGEXPS" ) = 1; +update MonitorPresets set Method = "simple" where Type = "Remote" and ( select Value from Config where Name = "ZM_NETCAM_REGEXPS" ) = 0; +update MonitorPresets set Method = "regexp" where Type = "Remote" and ( select Value from Config where Name = "ZM_NETCAM_REGEXPS" ) = 1; + +-- +-- Add subpath for remote RTSP monitors (only for now at least) +-- +alter table Monitors add column `SubPath` varchar(64) not null default '' after `Path`; +alter table MonitorPresets add column `SubPath` varchar(64) default NULL after `Path`; + +-- +-- Update Palette for new meaning as Colours for non-Local monitors +-- +update Monitors set Palette = 3 where Type != 'Local' and Palette = 4; +update MonitorPresets set Palette = 3 where Type != 'Local' and Palette = 4; + +-- +-- Update Method for Local monitors +-- +update Monitors set Method = "v4l1" where Type = 'Local'; + +-- +-- Add monitor type for FFMPEG cameras +-- +alter table Monitors modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local'; +alter table MonitorPresets modify column `Type` enum('Local','Remote','File','Ffmpeg') NOT NULL default 'Local'; + +-- +-- Fix columns to fit V4L2 formats and palettes +-- +alter table Monitors modify column `Format` int(10) unsigned NOT NULL default '0'; +alter table Monitors modify column `Palette` int(10) unsigned NOT NULL default '0'; +alter table MonitorPresets modify column `Channel` tinyint(3) unsigned default NULL; +alter table MonitorPresets modify column `Format` int(10) unsigned default NULL; +alter table MonitorPresets modify column `Palette` int(10) unsigned default NULL; + +-- +-- Add in new MPEG presets +-- +insert into MonitorPresets values ('','Axis IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +insert into MonitorPresets values ('','Axis IP, mpeg4, multicast','Remote',NULL,NULL,NULL,'rtsp','rtpMulti','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +insert into MonitorPresets values ('','Axis IP, mpeg4, RTP/RTSP','Remote',NULL,NULL,NULL,'rtsp','rtpRtsp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +insert into MonitorPresets values ('','Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); +insert into MonitorPresets values ('','ACTi IP, mpeg4, unicast','Remote',NULL,NULL,NULL,'rtsp','rtpUni','',7070,'','/track',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); + +-- +-- Get rid of never used columnn Learn State +-- +alter table Events drop column LearnState; + +-- +-- Update for new event close mode +-- +update Config set Value = "time" where Name = "ZM_EVENT_CLOSE_MODE" and ( select Value from ( select * from Config ) as TempConfig where Name = "ZM_FORCE_CLOSE_EVENTS" ) = 1; +update Config set Value = "idle" where Name = "ZM_EVENT_CLOSE_MODE" and ( select Value from ( select * from Config ) as TempConfig where Name = "ZM_FORCE_CLOSE_EVENTS" ) = 0; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.24.0.sql b/db/zm_update-1.24.0.sql new file mode 100644 index 000000000..ea2b2dcfa --- /dev/null +++ b/db/zm_update-1.24.0.sql @@ -0,0 +1,17 @@ +-- +-- This updates a 1.24.0 database to 1.24.1 +-- + +-- +-- No database changes +-- + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.24.1.sql b/db/zm_update-1.24.1.sql new file mode 100644 index 000000000..903ef0b81 --- /dev/null +++ b/db/zm_update-1.24.1.sql @@ -0,0 +1,34 @@ +-- +-- This updates a 1.24.1 database to the next version +-- + +-- +-- Replace local presets with V4L versioned ones +-- +delete from MonitorPresets where Type = 'Local'; +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 320x240, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), PAL, 640x480, max 5 FPS','Local','/dev/video','',255,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 320x240, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,320,240,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L2), NTSC, 640x480, max 5 FPS','Local','/dev/video','',45056,NULL,'v4l2',NULL,NULL,NULL,NULL,640,480,1345466932,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 320x240, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), PAL, 640x480, max 5 FPS','Local','/dev/video','',0,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 320x240, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,320,240,13,5.0,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO MonitorPresets VALUES ('','BTTV Video (V4L1), NTSC, 640x480, max 5 FPS','Local','/dev/video','',1,NULL,'v4l1',NULL,NULL,NULL,NULL,640,480,13,5.0,0,NULL,NULL,NULL,100,100); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.24.2.sql b/db/zm_update-1.24.2.sql new file mode 100644 index 000000000..0d93185e6 --- /dev/null +++ b/db/zm_update-1.24.2.sql @@ -0,0 +1,22 @@ +-- +-- This updates a 1.24.2 database to the next version +-- + +-- +-- Add in remote ZoneMinder preset. +-- +INSERT INTO `MonitorPresets` VALUES ('','Axis FFMPEG H.264','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp?videocodec=h264',NULL,NULL,NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO `MonitorPresets` VALUES ('','Vivotek FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://:554/live.sdp',NULL,NULL,NULL,352,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO `MonitorPresets` VALUES ('','Axis FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp:///axis-media/media.amp',NULL,NULL,NULL,640,480,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO `MonitorPresets` VALUES ('','ACTi TCM FFMPEG','Ffmpeg',NULL,NULL,NULL,NULL,NULL,'rtsp://admin:123456@:7070',NULL,NULL,NULL,320,240,NULL,NULL,0,NULL,NULL,NULL,100,100); +INSERT INTO `MonitorPresets` VALUES ('','Remote ZoneMinder','Remote',NULL,NULL,NULL,'http','simple','',80,'/cgi-bin/nph-zms?mode=jpeg&monitor=&scale=100&maxfps=5&buffer=0',NULL,NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100); + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.24.3.sql b/db/zm_update-1.24.3.sql new file mode 100644 index 000000000..6243e08fa --- /dev/null +++ b/db/zm_update-1.24.3.sql @@ -0,0 +1,13 @@ +-- +-- This updates a 1.24.3 database to the next version +-- + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-1.24.4.sql b/db/zm_update-1.24.4.sql new file mode 100644 index 000000000..49253e5c0 --- /dev/null +++ b/db/zm_update-1.24.4.sql @@ -0,0 +1,30 @@ +-- +-- This updates a 1.24.4 database to the next version +-- + +-- +-- Create Logs table +-- TODO - defaults to MyISAM as not easy to import selected engine +-- + +CREATE TABLE `Logs` ( + `TimeKey` decimal(16,6) NOT NULL, + `Component` varchar(32) NOT NULL, + `Pid` smallint(6) DEFAULT NULL, + `Level` tinyint(3) NOT NULL, + `Code` char(3) NOT NULL, + `Message` varchar(255) NOT NULL, + `File` varchar(255) DEFAULT NULL, + `Line` smallint(5) unsigned DEFAULT NULL, + KEY `TimeKey` (`TimeKey`) +) ENGINE=MyISAM; + +-- +-- These are optional, but we might as well do it now +-- +optimize table Frames; +optimize table Events; +optimize table Filters; +optimize table Zones; +optimize table Monitors; +optimize table Stats; diff --git a/db/zm_update-kfir-to-zum.sql b/db/zm_update-kfir-to-zum.sql new file mode 100644 index 000000000..be23f33f3 --- /dev/null +++ b/db/zm_update-kfir-to-zum.sql @@ -0,0 +1,24 @@ +-- +-- Table structure for table `PluginsConfig` +-- + +CREATE TABLE IF NOT EXISTS `PluginsConfig` ( + `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Name` varchar(32) NOT NULL DEFAULT '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `Choices` text NOT NULL, + `MonitorId` int(10) unsigned NOT NULL, + `ZoneId` int(10) unsigned NOT NULL, + `pluginName` tinytext NOT NULL, + PRIMARY KEY (`Id`), + KEY `ZoneId` (`ZoneId`), + KEY `MonitorId` (`MonitorId`), + KEY `Name` (`Name`), + FULLTEXT KEY `pluginName` (`pluginName`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; + + +ALTER TABLE `Monitors` ADD `UsedPl` varchar(88) NOT NULL default '' AFTER `Sequence`; +ALTER TABLE `Monitors` ADD `DoNativeMotDet` varchar(5) NOT NULL default 'yes' AFTER `UsedPl`; + diff --git a/db/zm_update_1.25.0-to-zum.sql b/db/zm_update_1.25.0-to-zum.sql new file mode 100644 index 000000000..e1b7b1575 --- /dev/null +++ b/db/zm_update_1.25.0-to-zum.sql @@ -0,0 +1,26 @@ +-- +-- Table structure for table `PluginsConfig` +-- + +CREATE TABLE IF NOT EXISTS `PluginsConfig` ( + `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `Name` varchar(32) NOT NULL DEFAULT '', + `Value` text NOT NULL, + `Type` tinytext NOT NULL, + `Choices` text NOT NULL, + `MonitorId` int(10) unsigned NOT NULL, + `ZoneId` int(10) unsigned NOT NULL, + `pluginName` tinytext NOT NULL, + PRIMARY KEY (`Id`), + KEY `ZoneId` (`ZoneId`), + KEY `MonitorId` (`MonitorId`), + KEY `Name` (`Name`), + FULLTEXT KEY `pluginName` (`pluginName`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; + + +ALTER TABLE `Monitors` ADD `UsedPl` varchar(88) NOT NULL default '' AFTER `Sequence`; +ALTER TABLE `Monitors` ADD `DoNativeMotDet` varchar(5) NOT NULL default 'yes' AFTER `UsedPl`; +ALTER TABLE `Monitors` ADD `Colours` TINYINT UNSIGNED NOT NULL DEFAULT '1' AFTER `Height`; +ALTER TABLE `Monitors` ADD `Deinterlacing` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `Orientation`; + diff --git a/depcomp b/depcomp new file mode 100755 index 000000000..807b991f4 --- /dev/null +++ b/depcomp @@ -0,0 +1,423 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" +fi + +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + tmpdepfile1="$dir.libs/$base.lo.d" + tmpdepfile2="$dir.libs/$base.d" + "$@" -Wc,-MD + else + tmpdepfile1="$dir$base.o.d" + tmpdepfile2="$dir$base.d" + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. We will use -o /dev/null later, + # however we can't do the remplacement now because + # `-o $object' might simply not be used + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + "$@" -o /dev/null $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/description-pak b/description-pak new file mode 100644 index 000000000..368e50fce --- /dev/null +++ b/description-pak @@ -0,0 +1 @@ +Zoneminder with kfir performances patches and plugin patches from UnixMedia diff --git a/doc-pak/AUTHORS b/doc-pak/AUTHORS new file mode 100644 index 000000000..7f0362072 --- /dev/null +++ b/doc-pak/AUTHORS @@ -0,0 +1,6 @@ +ZoneMinder - A Linux based camera monitoring and analysis tool. + +This project was imagined and created by Philip Coombes in +September 2002, shortly after being burglarised of his power tools. + +mailto:philip.coombes@zoneminder.com diff --git a/doc-pak/BUGS b/doc-pak/BUGS new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/doc-pak/BUGS @@ -0,0 +1 @@ +Please see README file. diff --git a/doc-pak/COPYING b/doc-pak/COPYING new file mode 100644 index 000000000..d60c31a97 --- /dev/null +++ b/doc-pak/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/doc-pak/ChangeLog b/doc-pak/ChangeLog new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/doc-pak/ChangeLog @@ -0,0 +1 @@ +Please see README file. diff --git a/doc-pak/INSTALL b/doc-pak/INSTALL new file mode 100644 index 000000000..1de0ac2ad --- /dev/null +++ b/doc-pak/INSTALL @@ -0,0 +1,185 @@ +Basic Installation +================== + + These are generic installation instructions. + + Please see http://www.zoneminder.com/wiki/index.php/Documentation + for full details. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/doc-pak/NEWS b/doc-pak/NEWS new file mode 100644 index 000000000..3160e2dce --- /dev/null +++ b/doc-pak/NEWS @@ -0,0 +1 @@ +Please see README file. diff --git a/doc-pak/README b/doc-pak/README new file mode 100644 index 000000000..e3dfa62e1 --- /dev/null +++ b/doc-pak/README @@ -0,0 +1,5 @@ + +All documentation for ZoneMinder is now online at + +http://www.zoneminder.com/wiki/index.php/Documentation + diff --git a/doc-pak/TODO b/doc-pak/TODO new file mode 100644 index 000000000..69af9c87e --- /dev/null +++ b/doc-pak/TODO @@ -0,0 +1,2 @@ +Please see README file. + diff --git a/install-sh b/install-sh new file mode 100755 index 000000000..e9de23842 --- /dev/null +++ b/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/misc/Makefile.am b/misc/Makefile.am new file mode 100644 index 000000000..3cd03a090 --- /dev/null +++ b/misc/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = gnu + +EXTRA_DIST = \ + apache.conf.in \ + logrotate.conf.in \ + syslog.conf.in diff --git a/misc/Makefile.in b/misc/Makefile.in new file mode 100644 index 000000000..8597872ce --- /dev/null +++ b/misc/Makefile.in @@ -0,0 +1,406 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = misc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/apache.conf.in $(srcdir)/logrotate.conf.in \ + $(srcdir)/syslog.conf.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = apache.conf logrotate.conf syslog.conf +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +EXTRA_DIST = \ + apache.conf.in \ + logrotate.conf.in \ + syslog.conf.in + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu misc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu misc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +apache.conf: $(top_builddir)/config.status $(srcdir)/apache.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +logrotate.conf: $(top_builddir)/config.status $(srcdir)/logrotate.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +syslog.conf: $(top_builddir)/config.status $(srcdir)/syslog.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/misc/apache.conf b/misc/apache.conf new file mode 100644 index 000000000..61b3df80e --- /dev/null +++ b/misc/apache.conf @@ -0,0 +1,39 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample configuration file for running ZoneMinder as name based virtual host +# Some values may need to manually adjusted to suit your setup +# + + ServerName zm.local + ServerAdmin webmaster@localhost + + DocumentRoot "/usr/share/zoneminder" + + Options FollowSymLinks + AllowOverride All + + + ScriptAlias /cgi-bin/ "/usr/lib/cgi-bin" + + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + AllowOverride All + + + # Use the first option to have Apache logs written to the general log + # directory, or the second to have them written to the regular Apache + # directory (you may have to change the path to that used on your system) + ErrorLog /var/log/zm/apache-error.log + ErrorLog /var/log/httpd/zm-error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + # Use the first option to have Apache logs written to the general log + # directory, or the second to have them written to the regular Apache + # directory (you may have to change the path to that used on your system) + CustomLog /var/log/zm/apache-access.log combined + CustomLog /var/log/httpd/zm-access.log combined + + diff --git a/misc/apache.conf.in b/misc/apache.conf.in new file mode 100644 index 000000000..06c9beb15 --- /dev/null +++ b/misc/apache.conf.in @@ -0,0 +1,39 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample configuration file for running ZoneMinder as name based virtual host +# Some values may need to manually adjusted to suit your setup +# + + ServerName @WEB_HOST@ + ServerAdmin webmaster@localhost + + DocumentRoot "@WEB_PREFIX@" + + Options FollowSymLinks + AllowOverride All + + + ScriptAlias /cgi-bin/ "@CGI_PREFIX@" + + Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch + AllowOverride All + + + # Use the first option to have Apache logs written to the general log + # directory, or the second to have them written to the regular Apache + # directory (you may have to change the path to that used on your system) + ErrorLog @ZM_LOGDIR@/apache-error.log + ErrorLog /var/log/httpd/zm-error.log + + # Possible values include: debug, info, notice, warn, error, crit, + # alert, emerg. + LogLevel warn + + # Use the first option to have Apache logs written to the general log + # directory, or the second to have them written to the regular Apache + # directory (you may have to change the path to that used on your system) + CustomLog @ZM_LOGDIR@/apache-access.log combined + CustomLog /var/log/httpd/zm-access.log combined + + diff --git a/misc/logrotate.conf b/misc/logrotate.conf new file mode 100644 index 000000000..4205ab899 --- /dev/null +++ b/misc/logrotate.conf @@ -0,0 +1,19 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample logrotate file for ZoneMinder. Copy this to /etc/logrotate.d/zm or similar +# if you wish your system to prevent your log files from growing too large. +# You can remove the 'kill' of syslogd if you have another logrotate file that does +# this but in that case you will want this file run first, so it will need to be +# named something lexically ahead of the other logrotate file, for example 0zm to +# ensure it is executed first. +# +/var/log/zm/*.log { + missingok + notifempty + sharedscripts + postrotate + /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true + /usr/bin/zmpkg.pl logrot 2> /dev/null > /dev/null || true + endscript +} diff --git a/misc/logrotate.conf.in b/misc/logrotate.conf.in new file mode 100644 index 000000000..664b206c3 --- /dev/null +++ b/misc/logrotate.conf.in @@ -0,0 +1,19 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample logrotate file for ZoneMinder. Copy this to /etc/logrotate.d/zm or similar +# if you wish your system to prevent your log files from growing too large. +# You can remove the 'kill' of syslogd if you have another logrotate file that does +# this but in that case you will want this file run first, so it will need to be +# named something lexically ahead of the other logrotate file, for example 0zm to +# ensure it is executed first. +# +@ZM_LOGDIR@/*.log { + missingok + notifempty + sharedscripts + postrotate + /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true + @BINDIR@/zmpkg.pl logrot 2> /dev/null > /dev/null || true + endscript +} diff --git a/misc/syslog.conf b/misc/syslog.conf new file mode 100644 index 000000000..79e8f8dcd --- /dev/null +++ b/misc/syslog.conf @@ -0,0 +1,19 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample instruction to put in /etc/syslog.conf (or rsyslog.conf) to redirect +# ZoneMinder syslog message to a separate file, apart from warnings and errors. +# This is done by assigning ZoneMinder messages to one of the user logging facilities +# which are local0-7. In this example local1 is used but if this is used by other +# packages then this can be changed to another which is unused (e.g. local3). +# + +# Save ZoneMinder messages to zm.log, this uses the local1 facility, +local1.* /var/log/zm/zm.log + +# You will need to edit the existing config line that directs to /var/log/messages +# or /var/log/syslog and insert the 'local1.!*;local1.warning' directives. This +# first excludes all local1 messages, and then re-enables local1 messages of warning +# level or above. Remove the second part if you want no ZoneMinder messages to go +# to your system logs at all. +*.info;local1.!*;local1.warning;mail.none;news.none;authpriv.none;cron.none /var/log/messages diff --git a/misc/syslog.conf.in b/misc/syslog.conf.in new file mode 100644 index 000000000..68df63eaa --- /dev/null +++ b/misc/syslog.conf.in @@ -0,0 +1,19 @@ +# +# PLEASE NOTE THAT THIS FILE IS INTENDED FOR GUIDANCE ONLY AND MAY NOT BE APPROPRIATE FOR YOUR DISTRIBUTION +# +# Sample instruction to put in /etc/syslog.conf (or rsyslog.conf) to redirect +# ZoneMinder syslog message to a separate file, apart from warnings and errors. +# This is done by assigning ZoneMinder messages to one of the user logging facilities +# which are local0-7. In this example local1 is used but if this is used by other +# packages then this can be changed to another which is unused (e.g. local3). +# + +# Save ZoneMinder messages to zm.log, this uses the local1 facility, +local1.* @ZM_LOGDIR@/zm.log + +# You will need to edit the existing config line that directs to /var/log/messages +# or /var/log/syslog and insert the 'local1.!*;local1.warning' directives. This +# first excludes all local1 messages, and then re-enables local1 messages of warning +# level or above. Remove the second part if you want no ZoneMinder messages to go +# to your system logs at all. +*.info;local1.!*;local1.warning;mail.none;news.none;authpriv.none;cron.none /var/log/messages diff --git a/missing b/missing new file mode 100755 index 000000000..6a37006e8 --- /dev/null +++ b/missing @@ -0,0 +1,336 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# 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, 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. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.4 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. + You can get \`$1Help2man' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/mkinstalldirs b/mkinstalldirs new file mode 100755 index 000000000..6b3b5fc5d --- /dev/null +++ b/mkinstalldirs @@ -0,0 +1,40 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman +# Created: 1993-05-16 +# Public domain + +# $Id$ + +errstatus=0 + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# mkinstalldirs ends here diff --git a/plugins/.sconsign.dblite b/plugins/.sconsign.dblite new file mode 100644 index 0000000000000000000000000000000000000000..fd10c8412d4c56290b8b57a5201cd1ecbd5ff779 GIT binary patch literal 44547 zcmeHQcbpu>l_m*1Zt!CgCd4-Jp?M!R-J(fF=w2YE6y3zuko zY+{n{7FlMo1A3zE>yXe(*WsbDS zVR&eQ9XY^`Y8(;<(d5MN5L>jlF}GD12@`Db09%3*CAvsiI>3(J9fIjmQ?^0ImVtV9 zV8L#A&W`EHM2%%-t*pq|${xWZo6|RR`8GU#B<_4{V`bzzkzspwZ0folXkKWiVH(A{ z7dWBg+9^9Oo7=zP(A{AsDkm$S|M;Ap(333~$QBM{#RFz|rW3P8n=^1fDFfY;1>N1f zjnmig@$tzu*Nv_j4JIZNKA9y~jt!^D>dVH*lK$bbIN__WOo#buElCaEwN@8mwMIzZ z4TGiREx2xUFil5yB}0QzFq-h7H~W{9IZ4E3_wB!C##U7d=RgRGTA$lk=|_S8X=-s~+it4aVdVLm#padrIluo;hg9-;SV#FhypVteIa?^p=Mjp09x2P`Q3IKv zrpV`_fl4|Tw@K%cfx2vxWG+G*@nm#-GAY|=kWWtR>dhp?xJnz)`FC8o(%Wb^yKJ`*A->LV*3d1cOy?GeIwNzvoIhrL$OK`M_ z<2-O2O-2WIPY&;#Q0O^1b5(j?&ip1l(H8_gR9_m#X5yQ+YX){;d7h@}jv2eQXGM|6 zP6xdO^K10Z$l00g^v){joh|5{L-b|}`5OuqV&~@UJeAnmoUN-9Gra(^rAMY029_QL zQJU(Z7FwYdJDTI@?0gVgcw~*(1vy*aPHaO-Y@;ByiHOYxv2b^q*4nf$XBVp6F3MRy zMrj&6nw`NiUB`6wFfh{q!*mctXj#+MyaZ!~ZdhzHxb-ipaodu!t!>;2X5iIgbsdIa z@&1;&=*2nPrn1_evmMPEJMGp&(jv>$HP>>yD2WX>jeHvn<4701)%0VJHNYynvBv6> zoIS3M6}z;ovB!%VyNtLUiW(zs^5AiK&Yqw$8_3xco6N3hGK=t!?|Vs%aU*pS!}sk7 zRP`j)q9_R1AeddUq{i%uoCWR7!jf4en8n2GpzB5z0ZVe0s-%W;mNiK=C13X}J53-^ zkrO3>Ygs{>8lmTfspgnQq_JU;`uKr0QX@ILvYphijYNytb=myBw_bR_el==O z%GvcDsLh3RVUn5-57n6EIlDn+c4N+NsyC*ALDhHDSc8Q5e(JbE5_)JyJB13WEfPgl7;BWJhOxuw1tM0jn6zMZG~Mcj97E@B(c5JHrX@5?e@hrZqLfuv)j2nr{wlr!R>j(Z4PQ~coc7^TE#s-XD?96 z-JY`-*2y^T`J`6lFNSxI04BK%0ATXTBv9usbL&G;r_6k(p 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 pcx~y1sC5$RG3Sa%=tP(`+paPgaiNp literal 0 HcmV?d00001 diff --git a/plugins/libzm_plugin_anpr/Makefile b/plugins/libzm_plugin_anpr/Makefile new file mode 100644 index 000000000..b6ec92f59 --- /dev/null +++ b/plugins/libzm_plugin_anpr/Makefile @@ -0,0 +1,60 @@ +#/*********************************************************************** +# This file is part of libzm_anpr_plugin, License Plate REcognition. +# +# Copyright (C) 2012 Franco (nextime) Lanza +# +# LiPRec is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# LiPRec 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 Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with LiPRec. If not, see . +#************************************************************************/ + + +OBJECTS = anpr_plugin.o +SOBJ=anpr_plugin.so + +ZMSRC = zm_detector.cpp zm_config.cpp zm_poly.cpp zm_zone.cpp zm_image.cpp zm_db.cpp +ZMSRC+= zm_logger.cpp zm_utils.cpp zm_thread.cpp zm_jpeg.cpp +ZMOBJ = $(ZMSRC:.cpp=.o) + +#CPPFLAGS= -fpermissive -O3 -march=native -Wall -lliprec -msse2 +CPPFLAGS= -fpermissive -O3 -Wall -lliprec -msse2 +CPPFLAGS+=-D__STDC_CONSTANT_MACROS -DZM_FFMPEG_CVS -DHAVE_LIBCRYPTO +CPPFLAGS+=-DJPEG_INCLUDE_DIR=../../../../../libjpeg-turbo-1.2.1/.libs/ +LDFLAGS=-L. -L../../../../../libjpeg-turbo-1.2.1/.libs/ +LDFLAGS+=-I../../src/ -I../../ -I./ +LDFLAGS+=-L/usr/lib -I/usr/include -I../../../../../libjpeg-turbo-1.2.1/ +LDFLAGS+=$(shell pkg-config --cflags opencv) + +LINKFLAGS=$(shell pkg-config --libs opencv) +LINKFLAGS+= -lliprec -lboost_program_options -lmysqlclient -lpthread -ljpeg -lz + + +all: anpr_plugin.o $(SOBJ) + + +$(ZMOBJ): %.o : ../../src/%.cpp + $(CXX) $^ -fPIC -c -o $@ ${LDFLAGS} $(CPPFLAGS) + +anpr_plugin.o: anpr_plugin.cpp + $(CXX) anpr_plugin.cpp -fPIC -c -o anpr_plugin.o ${LDFLAGS} $(CPPFLAGS) + +anpr_plugin.so: $(ZMOBJ) anpr_plugin.o + $(CXX) -o anpr_plugin.so -Wall anpr_plugin.o -shared $(ZMOBJ) $(LINKFLAGS) + cp anpr_plugin.so libzm_plugin_anpr.zmpl + +install: anpr_plugin.o $(SOBJ) + install -m 0644 libzm_plugin_anpr.zmpl /usr/share/zm/libzm_plugin_anpr.zmpl + $(shell cat plugin.conf >> /usr/share/zm/plugin.conf) + +clean: + rm -f $(OBJECTS) $(ZMOBJ) $(SOBJ) libzm_plugin_anpr.zmpl + diff --git a/plugins/libzm_plugin_anpr/anpr_plugin.cpp b/plugins/libzm_plugin_anpr/anpr_plugin.cpp new file mode 100644 index 000000000..987e4c748 --- /dev/null +++ b/plugins/libzm_plugin_anpr/anpr_plugin.cpp @@ -0,0 +1,250 @@ +/*********************************************************************** + This file is part of libzm_anpr_plugin, License Plate REcognition. + + Copyright (C) 2012 Franco (nextime) Lanza + + LiPRec is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LiPRec 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with LiPRec. If not, see . +************************************************************************/ + + +#define LIST LIPREC_LIST // This is a workaround to avoid the conflict +#include // of typedef LIST in both mysql and tesseract headers... +//#include "opencv2/highgui/highgui.hpp" +#undef LIST +#include "anpr_plugin.h" + +//! Retrieve the engine version we're going to expect +extern "C" int getEngineVersion() +{ + return ZM_ENGINE_VERSION; +} + +//! Tells us to register our functionality to an engine kernel +extern "C" void registerPlugin(PluginManager &PlM, string sPluginName) +{ + PlM.getImageAnalyser().addDetector( + auto_ptr(new ANPRPlugin(sPluginName)) + ); +} + + +using namespace cv; +//using namespace liprec; + +ANPRPlugin::ANPRPlugin() + : Detector(), + m_nMinObjSize(DEFAULT_DETECTOR_MIN_OBJECT_SIZE), + m_nMaxObjSize(DEFAULT_DETECTOR_MAX_OBJECT_SIZE) +{ + m_sDetectionCause = DETECTED_CAUSE; + m_sLogPrefix = LOG_PREFIX; + + + log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object has been created."); +} + + + + +ANPRPlugin::ANPRPlugin(string sPluginName) + : Detector(sPluginName), + m_nMinObjSize(DEFAULT_DETECTOR_MIN_OBJECT_SIZE), + m_nMaxObjSize(DEFAULT_DETECTOR_MAX_OBJECT_SIZE) +{ + m_sDetectionCause = DETECTED_CAUSE; + m_sLogPrefix = LOG_PREFIX; + + log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object has been created."); +} + + + +/*! \fn ANPRPlugin::loadConfig(string sConfigFileName) + * \param sConfigFileName is path to configuration to load parameters from + */ +void ANPRPlugin::loadConfig(string sConfigFileName) +{ + options_description config_file("Configuration file options."); + variables_map vm; + config_file.add_options() + ((m_sConfigSectionName + string(".min-obj-size")).c_str(), + value()->default_value(DEFAULT_DETECTOR_MIN_OBJECT_SIZE)) + ((m_sConfigSectionName + string(".max-obj-size")).c_str(), + value()->default_value(DEFAULT_DETECTOR_MAX_OBJECT_SIZE)) + ((m_sConfigSectionName + string(".alarm-score")).c_str(), + value()->default_value(DEFAULT_ALARM_SCORE)) + ((m_sConfigSectionName + string(".det-cause")).c_str(), + value()->default_value(DETECTED_CAUSE)) + ((m_sConfigSectionName + string(".log-prefix")).c_str(), + value()->default_value(LOG_PREFIX)) + ; + ifstream ifs(sConfigFileName.c_str()); + store(parse_config_file(ifs, config_file, true), vm); + notify(vm); + + m_nMinObjSize = vm[(m_sConfigSectionName + string(".min-obj-size")).c_str()].as(); + m_nMaxObjSize = vm[(m_sConfigSectionName + string(".max-obj-size")).c_str()].as(); + m_nAlarmScore = vm[(m_sConfigSectionName + string(".alarm-score")).c_str()].as(); + + m_sDetectionCause = vm[(m_sConfigSectionName + string(".det-cause")).c_str()].as(); + m_sLogPrefix = vm[(m_sConfigSectionName + string(".log-prefix")).c_str()].as(); + zmLoadConfig(); + log(LOG_NOTICE, "License Plate Recognition Plugin\'s Object is configured."); +} + + + +ANPRPlugin::~ANPRPlugin() +{ +} + + +/*! \fn ANPRPlugin::ANPRPlugin(const ANPRPlugin& source) + * \param source is the object for copying + */ +ANPRPlugin::ANPRPlugin(const ANPRPlugin& source) + : Detector(source), + m_nMinObjSize(source.m_nMinObjSize), + m_nMaxObjSize(source.m_nMaxObjSize) +{ +} + + + +/*! \fn ANPRPlugin:: operator=(const ANPRPlugin& source) + * \param source is the object for copying + */ +ANPRPlugin & ANPRPlugin:: operator=(const ANPRPlugin& source) +{ + Detector::operator=(source); + m_nMinObjSize = source.m_nMinObjSize; + m_nMaxObjSize = source.m_nMaxObjSize; + return *this; +} + + + + +/*! \fn ANPRPlugin::checkZone(Zone *zone, const Image *zmImage) + * \param zone is a zone where faces will be detected + * \param zmImage is an image to perform face detection (in the form of ZM' Image) + * \return true if there were objects detected in given image and + * false otherwise + */ +bool ANPRPlugin::checkZone(Zone *zone, const Image *zmImage) +{ + + double score; + Polygon zone_polygon = Polygon(zone->GetPolygon()); // Polygon of interest of the processed zone. + + Image *pMaskImage = new Image(zmImage->Width(), zmImage->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ); + pMaskImage->Fill(BLACK); + // An temporary image in the form of ZM for making from it CvMat. + // If don't use temp image, after rgb->bgr it will change. + Image *tempZmImage = new Image(*zmImage); + int imgtype=CV_8UC1; + if (tempZmImage->Colours() == ZM_COLOUR_RGB24) + imgtype=CV_8UC3; + Mat cvInputImage = Mat( + tempZmImage->Height(), + tempZmImage->Width(), + imgtype, (unsigned char*)tempZmImage->Buffer()).clone(); + //Mat cvInputImage = cvtmpInputImage.reshape(0, tempZmImage->Colours()); + //Mat cvInputImage = cvtmpInputImage.reshape(0, tempZmImage->Height()); + if (tempZmImage->Colours() == ZM_COLOUR_RGB24) + { + cvtColor(cvInputImage, cvInputImage, CV_RGB2BGR); + } + //imwrite("/tmp/sarca.jpg", cvInputImage); + //Process image + liprec::LiPRec plateDetector; + liprec::PlatesImage plates; + plateDetector.detectPlates(cvInputImage, &plates); + score = 0; + if(plates.plates.size() > 0) { + log(LOG_INFO, "PLATES WERE DETECTED"); + for(unsigned int i=0;iFill(WHITE, plateBox); + score=m_nAlarmScore; + delete plateBox; + } + } + + + if (score == 0) + { + //log(LOG_DEBUG, "No objects found. Exit."); + delete pMaskImage; + delete tempZmImage; + + // XXX We need to delete Mats? + + return( false ); + } + /* + else + { + zone->SetOverloadCount(zone->GetOverloadFrames()); + delete pMaskImage; + delete tempZmImage; + + return( false ); + }*/ + + + zone->SetScore((int)score); + + //Get mask by highlighting contours of objects and overlaying them with previous contours. + Rgb alarm_colour = RGB_GREEN; + Image *hlZmImage = pMaskImage->HighlightEdges(alarm_colour, ZM_COLOUR_RGB24, + ZM_SUBPIX_ORDER_RGB, &zone_polygon.Extent()); + + if (zone->Alarmed()) + { + // if there were previous detection and they have already set up alarm image + // then overlay it with current mask + Image* pPrevZoneMask = new Image(*(zone->AlarmImage())); + pPrevZoneMask->Overlay(*hlZmImage); + zone->SetAlarmImage(pPrevZoneMask); + delete pPrevZoneMask; + } + else + zone->SetAlarmImage(hlZmImage); + + delete pMaskImage; + delete hlZmImage; + delete tempZmImage; + + return true; +} + + diff --git a/plugins/libzm_plugin_anpr/anpr_plugin.h b/plugins/libzm_plugin_anpr/anpr_plugin.h new file mode 100644 index 000000000..ccab00eb2 --- /dev/null +++ b/plugins/libzm_plugin_anpr/anpr_plugin.h @@ -0,0 +1,89 @@ +/*********************************************************************** + This file is part of libzm_anpr_plugin, License Plate REcognition. + + Copyright (C) 2012 Franco (nextime) Lanza + + LiPRec is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LiPRec 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with LiPRec. If not, see . +************************************************************************/ + +#ifndef ANPR_PLUGIN_H +#define ANPR_PLUGIN_H + +#include +//#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "zm_plugin_manager.h" +#include "zm_detector.h" +#include "zm_rgb.h" + +#define DETECTED_CAUSE "Plate Detected" +#define LOG_PREFIX "ZM PLATEDEC PLUGIN" + + +#define DEFAULT_DETECTOR_MIN_OBJECT_SIZE 600 +#define DEFAULT_DETECTOR_MAX_OBJECT_SIZE 6000 +#define DEFAULT_ALARM_SCORE 99 + +using namespace std; +using namespace boost::program_options; + + +//! Face detector plugin class. +/*! The class derived from Detector. + * This class provides face detection based on OpenCV's implementation of Haar cascade classifier detector. + */ +class ANPRPlugin : public Detector { + public: + + //! Default Constructor. + ANPRPlugin(); + + //! Constructor. + ANPRPlugin(string sConfigSectionName); + + //! Destructor. + virtual ~ANPRPlugin(); + + //! Copy constructor. + ANPRPlugin(const ANPRPlugin& source); + + //! Overloaded operator=. + ANPRPlugin& operator=(const ANPRPlugin& source); + + void loadConfig(string sConfigFileName); + +protected: + + bool checkZone(Zone *zone, const Image *zmImage); + + int m_nMinObjSize; + int m_nMaxObjSize; + + int m_nAlarmScore; + +}; + + + +#endif // ANPR_PLUGIN_H + diff --git a/plugins/libzm_plugin_anpr/plugin.conf b/plugins/libzm_plugin_anpr/plugin.conf new file mode 100644 index 000000000..b947346a1 --- /dev/null +++ b/plugins/libzm_plugin_anpr/plugin.conf @@ -0,0 +1,8 @@ +[libzm_plugin_anpr] + +min-obj-size = 600 +max-obj-size = 6000 +alarm-score = 99 +det-cause = Plate Detected +log-prefix = PLATEDET PLUGIN + diff --git a/plugins/libzm_plugin_face_haar/.sconsign.dblite b/plugins/libzm_plugin_face_haar/.sconsign.dblite new file mode 100644 index 0000000000000000000000000000000000000000..d992fa609b40233ad33aa24c3e45ba229d9466af GIT binary patch literal 28235 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 + + + + 20 20 + + <_> + + + <_> + + <_> + + + + <_>2 7 16 4 -1. + <_>2 9 16 2 2. + 0 + 4.3272329494357109e-003 + 0.0383819006383419 + 1 + <_> + + + + <_>8 4 3 14 -1. + <_>8 11 3 7 2. + 0 + 0.0130761601030827 + 0.8965256810188294 + 0.2629314064979553 + <_> + + <_> + + + + <_>13 6 1 6 -1. + <_>13 9 1 3 2. + 0 + 5.2434601821005344e-004 + 0.1021663025021553 + 1 + <_> + + + + <_>4 2 12 8 -1. + <_>8 2 4 8 3. + 0 + 4.4573000632226467e-003 + 0.1238401979207993 + 0.6910383105278015 + <_> + + <_> + + + + <_>6 3 1 9 -1. + <_>6 6 1 3 3. + 0 + -9.2708261217921972e-004 + 1 + 0.1953697055578232 + <_> + + + + <_>3 7 14 9 -1. + <_>3 10 14 3 3. + 0 + 3.3989109215326607e-004 + 0.2101441025733948 + 0.8258674740791321 + 0.3506923019886017 + -1 + -1 + <_> + + + <_> + + <_> + + + + <_>4 7 4 4 -1. + <_>4 9 4 2 2. + 0 + 2.3025739938020706e-003 + 0.1018375977873802 + 1 + <_> + + + + <_>9 4 2 16 -1. + <_>9 12 2 8 2. + 0 + 4.4174338690936565e-003 + 0.8219057917594910 + 0.1956554949283600 + <_> + + <_> + + + + <_>1 1 18 5 -1. + <_>7 1 6 5 3. + 0 + 0.0222032107412815 + 0.2205407023429871 + 1 + <_> + + + + <_>4 5 13 8 -1. + <_>4 9 13 4 2. + 0 + -1.7283110355492681e-004 + 0.0732632577419281 + 0.5931484103202820 + <_> + + <_> + + + + <_>1 7 16 9 -1. + <_>1 10 16 3 3. + 0 + 4.3567270040512085e-003 + 0.1844114959239960 + 1 + <_> + + + + <_>2 0 15 4 -1. + <_>2 2 15 2 2. + 0 + -2.6032889727503061e-003 + 0.4032213985919952 + 0.8066521286964417 + <_> + + <_> + + + + <_>7 5 6 4 -1. + <_>9 5 2 4 3. + 0 + 1.7309630056843162e-003 + 0.2548328042030335 + 1 + <_> + + + + <_>6 3 8 9 -1. + <_>6 6 8 3 3. + 0 + -7.8146401792764664e-003 + 0.6057069897651672 + 0.2779063880443573 + <_> + + <_> + + + + <_>8 12 3 8 -1. + <_>8 16 3 4 2. + 0 + -8.7343417108058929e-003 + 0.2889980077743530 + 1 + <_> + + + + <_>3 16 2 2 -1. + <_>3 17 2 1 2. + 0 + 9.4522320432588458e-004 + 0.7616587281227112 + 0.3495643138885498 + <_> + + <_> + + + + <_>14 1 6 12 -1. + <_>14 1 3 12 2. + 0 + 0.0494148582220078 + 1 + 0.8151652812957764 + <_> + + + + <_>4 4 12 6 -1. + <_>8 4 4 6 3. + 0 + 4.4891750440001488e-003 + 0.2808783054351807 + 0.6027774810791016 + <_> + + <_> + + + + <_>0 2 6 15 -1. + <_>3 2 3 15 2. + 0 + 0.0603136196732521 + 1 + 0.7607501745223999 + <_> + + + + <_>5 4 9 6 -1. + <_>5 6 9 2 3. + 0 + -1.0762850288301706e-003 + 0.4444035887718201 + 0.1437312066555023 + <_> + + <_> + + + + <_>13 11 6 3 -1. + <_>13 12 6 1 3. + 0 + -9.5083238556981087e-003 + 1 + 0.5318170189857483 + <_> + + + + <_>12 12 6 4 -1. + <_>12 14 6 2 2. + 0 + 7.6601309701800346e-003 + 0.5411052107810974 + 0.2180687040090561 + <_> + + <_> + + + + <_>1 11 6 3 -1. + <_>1 12 6 1 3. + 0 + 7.6467678882181644e-003 + 1 + 0.1158960014581680 + <_> + + + + <_>2 5 5 8 -1. + <_>2 9 5 4 2. + 0 + -8.4662932204082608e-004 + 0.2340679019689560 + 0.5990381836891174 + 3.4721779823303223 + 0 + -1 + <_> + + + <_> + + <_> + + + + <_>5 4 10 4 -1. + <_>5 6 10 2 2. + 0 + -4.8506218008697033e-003 + 1 + 0.1805496066808701 + <_> + + + + <_>2 4 16 12 -1. + <_>2 8 16 4 3. + 0 + -4.6141650527715683e-003 + 0.2177893966436386 + 0.8018236756324768 + <_> + + <_> + + + + <_>4 5 12 6 -1. + <_>8 5 4 6 3. + 0 + -2.4301309604197741e-003 + 0.1141354963183403 + 1 + <_> + + + + <_>13 7 2 9 -1. + <_>13 10 2 3 3. + 0 + 4.1787960799410939e-004 + 0.1203093975782394 + 0.6108530759811401 + <_> + + <_> + + + + <_>5 7 2 9 -1. + <_>5 10 2 3 3. + 0 + 1.0010929545387626e-003 + 0.2079959958791733 + 1 + <_> + + + + <_>7 1 6 8 -1. + <_>9 1 2 8 3. + 0 + 1.0577100329101086e-003 + 0.3302054107189179 + 0.7511094212532044 + <_> + + <_> + + + + <_>12 0 4 12 -1. + <_>14 0 2 6 2. + <_>12 6 2 6 2. + 0 + 1.2376549420878291e-003 + 1 + 0.2768222093582153 + <_> + + + + <_>5 8 10 2 -1. + <_>5 9 10 1 2. + 0 + 3.5315038985572755e-004 + 0.1668293029069901 + 0.5829476714134216 + <_> + + <_> + + + + <_>5 1 6 4 -1. + <_>7 1 2 4 3. + 0 + -0.0119536602869630 + 0.1508788019418716 + 1 + <_> + + + + <_>0 3 9 12 -1. + <_>3 3 3 12 3. + 0 + 1.4182999730110168e-003 + 0.4391227960586548 + 0.7646595239639282 + <_> + + <_> + + + + <_>9 8 3 12 -1. + <_>9 12 3 4 3. + 0 + 3.4642980899661779e-003 + 1 + 0.2651556134223938 + <_> + + + + <_>0 5 20 15 -1. + <_>0 10 20 5 3. + 0 + -0.0149489501491189 + 0.2298053056001663 + 0.5442165732383728 + <_> + + <_> + + + + <_>2 2 6 8 -1. + <_>2 2 3 4 2. + <_>5 6 3 4 2. + 0 + -1.0506849503144622e-003 + 1 + 0.3622843921184540 + <_> + + + + <_>2 1 6 2 -1. + <_>2 2 6 1 2. + 0 + -4.0782918222248554e-003 + 0.2601259946823120 + 0.7233657836914063 + <_> + + <_> + + + + <_>10 15 6 4 -1. + <_>13 15 3 2 2. + <_>10 17 3 2 2. + 0 + 5.4242828628048301e-004 + 0.3849678933620453 + 1 + <_> + + + + <_>12 14 2 6 -1. + <_>12 16 2 2 3. + 0 + -7.3204059153795242e-003 + 0.2965512871742249 + 0.5480309128761292 + <_> + + <_> + + + + <_>5 15 4 4 -1. + <_>5 15 2 2 2. + <_>7 17 2 2 2. + 0 + 1.1421289527788758e-003 + 0.4104770123958588 + 1 + <_> + + + + <_>7 18 1 2 -1. + <_>7 19 1 1 2. + 0 + 1.1783400550484657e-003 + 0.7239024043083191 + 0.2787283957004547 + <_> + + <_> + + + + <_>4 5 12 10 -1. + <_>10 5 6 5 2. + <_>4 10 6 5 2. + 0 + 0.0440771095454693 + 0.5640516281127930 + 1 + <_> + + + + <_>7 4 8 12 -1. + <_>11 4 4 6 2. + <_>7 10 4 6 2. + 0 + 3.7900090683251619e-003 + 0.5947548151016235 + 0.3312020003795624 + <_> + + <_> + + + + <_>9 11 2 3 -1. + <_>9 12 2 1 3. + 0 + -2.4291418958455324e-003 + 0.6603232026100159 + 1 + <_> + + + + <_>3 3 12 12 -1. + <_>3 3 6 6 2. + <_>9 9 6 6 2. + 0 + 9.4262324273586273e-003 + 0.4680665135383606 + 0.2064338028430939 + <_> + + <_> + + + + <_>15 11 5 3 -1. + <_>15 12 5 1 3. + 0 + 8.0630257725715637e-003 + 0.5298851132392883 + 1 + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + 5.2240812219679356e-003 + 0.5281602740287781 + 0.1909549981355667 + <_> + + <_> + + + + <_>0 11 5 3 -1. + <_>0 12 5 1 3. + 0 + -7.0630568079650402e-003 + 0.1380645930767059 + 1 + <_> + + + + <_>7 18 3 2 -1. + <_>8 18 1 2 3. + 0 + 5.6897541508078575e-003 + 0.5490636825561523 + 0.1260281056165695 + <_> + + <_> + + + + <_>2 8 16 2 -1. + <_>2 9 16 1 2. + 0 + 1.2472929665818810e-003 + 0.2372663021087647 + 1 + <_> + + + + <_>9 6 5 12 -1. + <_>9 12 5 6 2. + 0 + 0.0495434887707233 + 0.5240166187286377 + 0.1769216060638428 + 5.9844889640808105 + 1 + -1 + <_> + + + <_> + + <_> + + + + <_>6 3 8 6 -1. + <_>6 6 8 3 2. + 0 + -4.9326149746775627e-003 + 1 + 0.1998064965009689 + <_> + + + + <_>4 7 12 2 -1. + <_>8 7 4 2 3. + 0 + 2.7918140403926373e-005 + 0.2299380004405975 + 0.7393211126327515 + <_> + + <_> + + + + <_>10 9 6 8 -1. + <_>10 13 6 4 2. + 0 + 3.0876200180500746e-003 + 1 + 0.1533840000629425 + <_> + + + + <_>12 5 3 10 -1. + <_>12 10 3 5 2. + 0 + 7.4669660534709692e-006 + 0.2036858946084976 + 0.5854915976524353 + <_> + + <_> + + + + <_>4 6 3 9 -1. + <_>4 9 3 3 3. + 0 + 1.8739729421213269e-003 + 0.2049895972013474 + 1 + <_> + + + + <_>7 4 6 4 -1. + <_>9 4 2 4 3. + 0 + 9.3380251200869679e-004 + 0.3234199881553650 + 0.7323014140129089 + <_> + + <_> + + + + <_>12 3 8 3 -1. + <_>12 3 4 3 2. + 0 + 1.9151850137859583e-003 + 0.3045149147510529 + 1 + <_> + + + + <_>15 0 3 6 -1. + <_>15 3 3 3 2. + 0 + -5.9683797881007195e-003 + 0.2932133972644806 + 0.5621296167373657 + <_> + + <_> + + + + <_>2 12 10 8 -1. + <_>2 12 5 4 2. + <_>7 16 5 4 2. + 0 + -7.2115601506084204e-004 + 0.3658036887645721 + 1 + <_> + + + + <_>5 5 6 8 -1. + <_>5 9 6 4 2. + 0 + -5.9663117863237858e-003 + 0.2712155878543854 + 0.7226334810256958 + <_> + + <_> + + + + <_>12 3 8 3 -1. + <_>12 3 4 3 2. + 0 + 0.0308741796761751 + 0.4419837892055512 + 1 + <_> + + + + <_>15 0 3 6 -1. + <_>15 3 3 3 2. + 0 + -0.0110997101292014 + 0.3612976968288422 + 0.5251451134681702 + <_> + + <_> + + + + <_>0 3 8 3 -1. + <_>4 3 4 3 2. + 0 + 2.1164179779589176e-003 + 0.3628616929054260 + 1 + <_> + + + + <_>2 1 4 4 -1. + <_>2 3 4 2 2. + 0 + -9.4317439943552017e-003 + 0.1601095050573349 + 0.7052276730537415 + <_> + + <_> + + + + <_>10 2 3 2 -1. + <_>11 2 1 2 3. + 0 + -3.5266019403934479e-003 + 0.1301288008689880 + 1 + <_> + + + + <_>10 3 3 1 -1. + <_>11 3 1 1 3. + 0 + -1.6907559474930167e-003 + 0.1786323934793472 + 0.5521529912948608 + <_> + + <_> + + + + <_>7 15 3 4 -1. + <_>7 17 3 2 2. + 0 + 4.6470930101349950e-004 + 0.3487383127212524 + 1 + <_> + + + + <_>4 13 3 6 -1. + <_>4 15 3 2 3. + 0 + -0.0102155702188611 + 0.2673991024494171 + 0.6667919158935547 + <_> + + <_> + + + + <_>10 5 1 14 -1. + <_>10 12 1 7 2. + 0 + 1.2634709710255265e-003 + 1 + 0.3437863886356354 + <_> + + + + <_>5 4 10 6 -1. + <_>5 6 10 2 3. + 0 + -0.0118752997368574 + 0.5995336174964905 + 0.3497717976570129 + <_> + + <_> + + + + <_>5 0 6 3 -1. + <_>7 0 2 3 3. + 0 + -0.0107323396950960 + 0.2150489985942841 + 1 + <_> + + + + <_>6 0 3 5 -1. + <_>7 0 1 5 3. + 0 + 7.1836481802165508e-003 + 0.6271436214447022 + 0.2519541978836060 + <_> + + <_> + + + + <_>7 15 6 5 -1. + <_>9 15 2 5 3. + 0 + -0.0283408891409636 + 0.0824118927121162 + 1 + <_> + + + + <_>9 10 2 6 -1. + <_>9 12 2 2 3. + 0 + -4.5813230099156499e-004 + 0.5910056829452515 + 0.3705201148986816 + <_> + + <_> + + + + <_>8 17 3 2 -1. + <_>9 17 1 2 3. + 0 + 4.2940340936183929e-003 + 1 + 0.1594727933406830 + <_> + + + + <_>1 12 7 6 -1. + <_>1 14 7 2 3. + 0 + 0.0107510797679424 + 0.5980480909347534 + 0.2832508087158203 + <_> + + <_> + + + + <_>9 6 3 7 -1. + <_>10 6 1 7 3. + 0 + 0.0224651191383600 + 1 + 0.7877091169357300 + <_> + + + + <_>16 3 4 9 -1. + <_>16 6 4 3 3. + 0 + -0.0579885393381119 + 0.1555740982294083 + 0.5239657163619995 + <_> + + <_> + + + + <_>8 6 3 7 -1. + <_>9 6 1 7 3. + 0 + 7.2110891342163086e-003 + 1 + 0.6620365977287293 + <_> + + + + <_>0 5 18 8 -1. + <_>0 5 9 4 2. + <_>9 9 9 4 2. + 0 + -0.0483675710856915 + 0.1424719989299774 + 0.4429833889007568 + <_> + + <_> + + + + <_>13 5 2 10 -1. + <_>13 10 2 5 2. + 0 + -0.0144180599600077 + 0.1588540971279144 + 1 + <_> + + + + <_>12 10 2 6 -1. + <_>12 13 2 3 2. + 0 + -0.0231563895940781 + 0.2375798970460892 + 0.5217134952545166 + <_> + + <_> + + + + <_>7 0 3 5 -1. + <_>8 0 1 5 3. + 0 + 7.6985340565443039e-003 + 1 + 0.1941725015640259 + <_> + + + + <_>6 5 8 6 -1. + <_>6 7 8 2 3. + 0 + -5.6248619221150875e-003 + 0.6278405785560608 + 0.3746044933795929 + <_> + + <_> + + + + <_>10 3 6 14 -1. + <_>13 3 3 7 2. + <_>10 10 3 7 2. + 0 + -7.2936748620122671e-004 + 1 + 0.3840922117233276 + <_> + + + + <_>13 5 1 8 -1. + <_>13 9 1 4 2. + 0 + 6.1783898854628205e-004 + 0.3106493055820465 + 0.5537847280502319 + <_> + + <_> + + + + <_>4 3 6 14 -1. + <_>4 3 3 7 2. + <_>7 10 3 7 2. + 0 + -4.5803939428878948e-005 + 1 + 0.3444449007511139 + <_> + + + + <_>6 5 1 8 -1. + <_>6 9 1 4 2. + 0 + -1.4719359569426160e-005 + 0.2729552090167999 + 0.6428951025009155 + 8.5117864608764648 + 2 + -1 + <_> + + + <_> + + <_> + + + + <_>8 1 1 6 -1. + <_>8 3 1 2 3. + 0 + -1.3469370314851403e-003 + 0.1657086014747620 + 1 + <_> + + + + <_>2 0 15 2 -1. + <_>2 1 15 1 2. + 0 + -2.4774789344519377e-003 + 0.2273851037025452 + 0.6989349722862244 + <_> + + <_> + + + + <_>0 7 20 6 -1. + <_>0 9 20 2 3. + 0 + 5.2632777951657772e-003 + 0.1512074023485184 + 1 + <_> + + + + <_>10 10 6 8 -1. + <_>10 14 6 4 2. + 0 + 4.9075339920818806e-003 + 0.5564470291137695 + 0.1605442017316818 + <_> + + <_> + + + + <_>7 1 3 2 -1. + <_>8 1 1 2 3. + 0 + -2.3254349362105131e-003 + 0.1880259066820145 + 1 + <_> + + + + <_>8 1 2 2 -1. + <_>9 1 1 2 2. + 0 + -1.4665479538962245e-003 + 0.3122498989105225 + 0.7165396213531494 + <_> + + <_> + + + + <_>4 3 12 9 -1. + <_>4 6 12 3 3. + 0 + -0.1231169030070305 + 1 + 0.3859583139419556 + <_> + + + + <_>6 5 9 5 -1. + <_>9 5 3 5 3. + 0 + 2.2108340635895729e-003 + 0.2455293983221054 + 0.5695710182189941 + <_> + + <_> + + + + <_>5 5 9 5 -1. + <_>8 5 3 5 3. + 0 + 2.0661531016230583e-003 + 0.2716520130634308 + 1 + <_> + + + + <_>4 6 6 12 -1. + <_>4 10 6 4 3. + 0 + 3.6130280932411551e-004 + 0.2293362021446228 + 0.7208629846572876 + <_> + + <_> + + + + <_>13 0 6 18 -1. + <_>13 0 3 18 2. + 0 + 0.0799578726291656 + 1 + 0.7833620905876160 + <_> + + + + <_>10 8 1 12 -1. + <_>10 12 1 4 3. + 0 + 2.6064720004796982e-003 + 0.5545232295989990 + 0.2550689876079559 + <_> + + <_> + + + + <_>3 2 6 10 -1. + <_>3 2 3 5 2. + <_>6 7 3 5 2. + 0 + 6.5699010156095028e-003 + 1 + 0.1819390058517456 + <_> + + + + <_>1 2 4 6 -1. + <_>3 2 2 6 2. + 0 + 1.6259610420092940e-003 + 0.3529875874519348 + 0.6552819013595581 + <_> + + <_> + + + + <_>9 18 3 2 -1. + <_>10 18 1 2 3. + 0 + 3.6204981151968241e-003 + 0.5462309718132019 + 1 + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + -4.4391951523721218e-003 + 0.1359843015670776 + 0.5415815114974976 + <_> + + <_> + + + + <_>2 8 2 6 -1. + <_>2 10 2 2 3. + 0 + -9.0540945529937744e-003 + 0.1115119978785515 + 1 + <_> + + + + <_>7 5 6 6 -1. + <_>7 7 6 2 3. + 0 + -4.6067481162026525e-004 + 0.5846719741821289 + 0.2598348855972290 + <_> + + <_> + + + + <_>7 19 6 1 -1. + <_>9 19 2 1 3. + 0 + -5.6621041148900986e-003 + 0.1610569059848785 + 1 + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + 5.1165837794542313e-003 + 0.5376678705215454 + 0.1739455014467239 + <_> + + <_> + + + + <_>8 3 3 1 -1. + <_>9 3 1 1 3. + 0 + -2.1362339612096548e-003 + 0.1902073025703430 + 1 + <_> + + + + <_>2 2 16 2 -1. + <_>2 2 8 1 2. + <_>10 3 8 1 2. + 0 + -5.4809921421110630e-003 + 0.3272008001804352 + 0.6364840865135193 + <_> + + <_> + + + + <_>8 11 5 3 -1. + <_>8 12 5 1 3. + 0 + -8.1061907112598419e-003 + 0.6914852857589722 + 1 + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + 6.0048708692193031e-003 + 0.4327326118946075 + 0.6963843107223511 + <_> + + <_> + + + + <_>0 1 6 15 -1. + <_>2 1 2 15 3. + 0 + -0.0870285481214523 + 0.8594133853912354 + 1 + <_> + + + + <_>2 12 2 3 -1. + <_>2 13 2 1 3. + 0 + -4.7809639945626259e-003 + 0.0973944664001465 + 0.4587030112743378 + <_> + + <_> + + + + <_>16 13 1 3 -1. + <_>16 14 1 1 3. + 0 + -2.2166660055518150e-003 + 0.2554625868797302 + 1 + <_> + + + + <_>13 7 6 4 -1. + <_>16 7 3 2 2. + <_>13 9 3 2 2. + 0 + 1.3642730191349983e-003 + 0.3319090902805328 + 0.5964102745056152 + <_> + + <_> + + + + <_>7 13 3 6 -1. + <_>7 16 3 3 2. + 0 + -9.0077864006161690e-003 + 0.2666594982147217 + 1 + <_> + + + + <_>7 5 1 14 -1. + <_>7 12 1 7 2. + 0 + -0.0154941203072667 + 0.1848185956478119 + 0.6245970726013184 + <_> + + <_> + + + + <_>15 12 2 3 -1. + <_>15 13 2 1 3. + 0 + -4.2165028862655163e-003 + 1 + 0.5379927158355713 + <_> + + + + <_>10 5 3 14 -1. + <_>10 12 3 7 2. + 0 + 0.0432497598230839 + 0.5183029174804688 + 0.2170419991016388 + <_> + + <_> + + + + <_>6 10 2 6 -1. + <_>6 13 2 3 2. + 0 + 2.8786511393263936e-004 + 1 + 0.2613384127616882 + <_> + + + + <_>6 5 1 8 -1. + <_>6 9 1 4 2. + 0 + 1.2373150093480945e-003 + 0.2786532044410706 + 0.5908988118171692 + <_> + + <_> + + + + <_>13 11 2 1 -1. + <_>13 11 1 1 2. + 0 + 1.9528300035744905e-003 + 1 + 0.2612869143486023 + <_> + + + + <_>12 1 6 10 -1. + <_>15 1 3 5 2. + <_>12 6 3 5 2. + 0 + -1.4947060262784362e-003 + 0.5915412902832031 + 0.3455781936645508 + <_> + + <_> + + + + <_>3 12 2 3 -1. + <_>3 13 2 1 3. + 0 + 3.5878680646419525e-003 + 1 + 0.1587052047252655 + <_> + + + + <_>9 18 2 1 -1. + <_>10 18 1 1 2. + 0 + -2.5938691105693579e-003 + 0.1270411014556885 + 0.5979428887367249 + 8.4680156707763672 + 3 + -1 + <_> + + + <_> + + <_> + + + + <_>1 0 17 9 -1. + <_>1 3 17 3 3. + 0 + 3.5810680128633976e-003 + 0.1995104998350143 + 1 + <_> + + + + <_>1 2 8 8 -1. + <_>1 2 4 4 2. + <_>5 6 4 4 2. + 0 + -2.8552350122481585e-003 + 0.7373070120811462 + 0.2921737134456635 + <_> + + <_> + + + + <_>9 5 6 4 -1. + <_>9 5 3 4 2. + 0 + 1.9758539274334908e-003 + 0.1956419944763184 + 1 + <_> + + + + <_>10 9 7 10 -1. + <_>10 14 7 5 2. + 0 + 3.2583118882030249e-003 + 0.5692046880722046 + 0.1839064955711365 + <_> + + <_> + + + + <_>5 5 6 4 -1. + <_>8 5 3 4 2. + 0 + 2.3711679386906326e-004 + 0.2171667069196701 + 1 + <_> + + + + <_>0 7 20 6 -1. + <_>0 9 20 2 3. + 0 + 2.5942500215023756e-003 + 0.2719989120960236 + 0.7150244116783142 + <_> + + <_> + + + + <_>6 5 9 10 -1. + <_>6 10 9 5 2. + 0 + -0.0250324495136738 + 0.1825183928012848 + 1 + <_> + + + + <_>8 4 4 12 -1. + <_>8 10 4 6 2. + 0 + 6.3087949529290199e-003 + 0.5699837803840637 + 0.3509852886199951 + <_> + + <_> + + + + <_>6 6 8 3 -1. + <_>6 7 8 1 3. + 0 + -3.2494920305907726e-003 + 1 + 0.4023926854133606 + <_> + + + + <_>3 13 10 6 -1. + <_>3 13 5 3 2. + <_>8 16 5 3 2. + 0 + -0.0148857301101089 + 0.3604095876216888 + 0.7291995286941528 + <_> + + <_> + + + + <_>15 1 4 11 -1. + <_>15 1 2 11 2. + 0 + 8.0623216927051544e-003 + 1 + 0.6491490006446838 + <_> + + + + <_>5 7 10 10 -1. + <_>10 7 5 5 2. + <_>5 12 5 5 2. + 0 + 0.0274056792259216 + 0.5518993139266968 + 0.2659681141376495 + <_> + + <_> + + + + <_>1 1 4 11 -1. + <_>3 1 2 11 2. + 0 + 0.0343686006963253 + 1 + 0.6712512969970703 + <_> + + + + <_>1 5 8 12 -1. + <_>1 11 8 6 2. + 0 + -0.0272929705679417 + 0.1691378057003021 + 0.4326277971267700 + <_> + + <_> + + + + <_>13 7 6 4 -1. + <_>16 7 3 2 2. + <_>13 9 3 2 2. + 0 + 7.4452121043577790e-004 + 0.3405100107192993 + 1 + <_> + + + + <_>11 10 7 4 -1. + <_>11 12 7 2 2. + 0 + 7.0336280623450875e-004 + 0.5516793131828308 + 0.3311387896537781 + <_> + + <_> + + + + <_>0 4 20 12 -1. + <_>0 4 10 6 2. + <_>10 10 10 6 2. + 0 + -0.1227546036243439 + 0.1675315052270889 + 1 + <_> + + + + <_>1 5 6 15 -1. + <_>1 10 6 5 3. + 0 + 3.2559928949922323e-003 + 0.3615751862525940 + 0.6420782804489136 + <_> + + <_> + + + + <_>11 10 3 8 -1. + <_>11 14 3 4 2. + 0 + -0.0320903994143009 + 0.2921079099178314 + 1 + <_> + + + + <_>11 12 7 6 -1. + <_>11 14 7 2 3. + 0 + 3.2957999501377344e-003 + 0.5613031983375549 + 0.3357860147953033 + <_> + + <_> + + + + <_>9 11 2 3 -1. + <_>9 12 2 1 3. + 0 + -3.2273170072585344e-003 + 0.6970642805099487 + 1 + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 1.1171669466421008e-003 + 0.3541150093078613 + 0.6144006252288818 + <_> + + <_> + + + + <_>3 14 14 4 -1. + <_>10 14 7 2 2. + <_>3 16 7 2 2. + 0 + -0.0172799509018660 + 1 + 0.5537180900573731 + <_> + + + + <_>18 7 2 4 -1. + <_>18 9 2 2 2. + 0 + 0.0117412004619837 + 0.5341957211494446 + 0.2757104933261871 + <_> + + <_> + + + + <_>3 12 6 6 -1. + <_>3 14 6 2 3. + 0 + 4.6405228786170483e-003 + 1 + 0.2489521056413651 + <_> + + + + <_>0 4 3 6 -1. + <_>0 6 3 2 3. + 0 + -0.0169130302965641 + 0.1711928993463516 + 0.5523952841758728 + <_> + + <_> + + + + <_>9 14 3 3 -1. + <_>9 15 3 1 3. + 0 + 0.0100601697340608 + 1 + 0.8273450732231140 + <_> + + + + <_>10 7 10 4 -1. + <_>15 7 5 2 2. + <_>10 9 5 2 2. + 0 + -6.0715491417795420e-004 + 0.3779391050338745 + 0.5476251840591431 + <_> + + <_> + + + + <_>7 2 6 8 -1. + <_>7 6 6 4 2. + 0 + -1.0865400545299053e-003 + 1 + 0.3296540975570679 + <_> + + + + <_>6 3 6 2 -1. + <_>8 3 2 2 3. + 0 + 8.9362077414989471e-003 + 0.6062883734703064 + 0.2434220016002655 + <_> + + <_> + + + + <_>10 6 3 5 -1. + <_>11 6 1 5 3. + 0 + -2.6372660067863762e-004 + 1 + 0.3814094960689545 + <_> + + + + <_>9 0 6 19 -1. + <_>11 0 2 19 3. + 0 + 0.0131100500002503 + 0.5517616271972656 + 0.3726893067359924 + <_> + + <_> + + + + <_>3 12 1 2 -1. + <_>3 13 1 1 2. + 0 + -2.9806280508637428e-003 + 0.1229664012789726 + 1 + <_> + + + + <_>7 14 5 3 -1. + <_>7 15 5 1 3. + 0 + -4.1619571857154369e-003 + 0.7252274751663208 + 0.4973455071449280 + <_> + + <_> + + + + <_>2 1 18 4 -1. + <_>11 1 9 2 2. + <_>2 3 9 2 2. + 0 + 0.0338423289358616 + 0.5348312854766846 + 1 + <_> + + + + <_>10 5 3 8 -1. + <_>11 5 1 8 3. + 0 + -1.2564560165628791e-003 + 0.5851914882659912 + 0.4384166896343231 + <_> + + <_> + + + + <_>0 1 18 4 -1. + <_>0 1 9 2 2. + <_>9 3 9 2 2. + 0 + -0.0196352303028107 + 0.2297834008932114 + 1 + <_> + + + + <_>7 5 3 8 -1. + <_>8 5 1 8 3. + 0 + -9.9625496659427881e-004 + 0.6295937895774841 + 0.4131599068641663 + <_> + + <_> + + + + <_>9 5 2 6 -1. + <_>9 7 2 2 3. + 0 + -0.0231271106749773 + 0.1695459038019180 + 1 + <_> + + + + <_>10 8 5 2 -1. + <_>10 9 5 1 2. + 0 + 0.0235257092863321 + 0.5174130201339722 + 0.0595193915069103 + <_> + + <_> + + + + <_>2 10 15 1 -1. + <_>7 10 5 1 3. + 0 + -0.0193565208464861 + 0.1357247978448868 + 1 + <_> + + + + <_>2 7 2 6 -1. + <_>2 9 2 2 3. + 0 + -4.1787112131714821e-003 + 0.2996628880500794 + 0.5791695117950440 + <_> + + <_> + + + + <_>9 14 3 3 -1. + <_>9 15 3 1 3. + 0 + 3.1488779932260513e-003 + 1 + 0.6592589020729065 + <_> + + + + <_>9 7 4 10 -1. + <_>9 12 4 5 2. + 0 + 7.3972279205918312e-003 + 0.5307171940803528 + 0.3795121014118195 + <_> + + <_> + + + + <_>0 8 8 2 -1. + <_>0 8 4 1 2. + <_>4 9 4 1 2. + 0 + 7.1955118983169086e-006 + 0.3128314912319183 + 1 + <_> + + + + <_>5 9 10 8 -1. + <_>5 9 5 4 2. + <_>10 13 5 4 2. + 0 + 0.0471144095063210 + 0.5537893176078796 + 0.1027309000492096 + <_> + + <_> + + + + <_>9 7 2 4 -1. + <_>9 7 1 4 2. + 0 + 7.2878710925579071e-003 + 0.4660859107971191 + 1 + <_> + + + + <_>9 6 3 4 -1. + <_>10 6 1 4 3. + 0 + -6.1887511983513832e-003 + 0.7158858180046082 + 0.4724448919296265 + <_> + + <_> + + + + <_>8 3 2 1 -1. + <_>9 3 1 1 2. + 0 + 2.9757320880889893e-003 + 1 + 0.0593456886708736 + <_> + + + + <_>8 6 3 4 -1. + <_>9 6 1 4 3. + 0 + -1.8449809867888689e-003 + 0.7027301788330078 + 0.4718731045722961 + <_> + + <_> + + + + <_>12 0 4 14 -1. + <_>14 0 2 7 2. + <_>12 7 2 7 2. + 0 + 1.0239540279144421e-004 + 0.5894734263420105 + 1 + <_> + + + + <_>12 5 6 9 -1. + <_>12 5 3 9 2. + 0 + 2.4277009069919586e-003 + 0.4862355887889862 + 0.5247588157653809 + <_> + + <_> + + + + <_>0 2 6 16 -1. + <_>3 2 3 16 2. + 0 + -0.0647513121366501 + 0.6917471289634705 + 1 + <_> + + + + <_>1 12 4 2 -1. + <_>1 13 4 1 2. + 0 + 3.9380151429213583e-004 + 0.4669617116451263 + 0.2382405996322632 + 12.5784997940063480 + 4 + -1 + <_> + + + <_> + + <_> + + + + <_>7 7 6 1 -1. + <_>9 7 2 1 3. + 0 + 1.4397440245375037e-003 + 0.2773470878601074 + 1 + <_> + + + + <_>8 3 4 9 -1. + <_>8 6 4 3 3. + 0 + -5.4068560712039471e-004 + 0.7427154779434204 + 0.2479735016822815 + <_> + + <_> + + + + <_>12 10 4 6 -1. + <_>12 13 4 3 2. + 0 + -7.1237959673453588e-006 + 1 + 0.2199503034353256 + <_> + + + + <_>8 1 8 16 -1. + <_>12 1 4 8 2. + <_>8 9 4 8 2. + 0 + -2.3661039303988218e-003 + 0.5889989733695984 + 0.2595716118812561 + <_> + + <_> + + + + <_>4 6 3 6 -1. + <_>4 9 3 3 2. + 0 + 1.7343269428238273e-003 + 0.1860125958919525 + 1 + <_> + + + + <_>1 3 6 2 -1. + <_>4 3 3 2 2. + 0 + 1.5874590026214719e-003 + 0.4151870906352997 + 0.7103474140167236 + <_> + + <_> + + + + <_>9 8 3 12 -1. + <_>9 12 3 4 3. + 0 + 3.7285638973116875e-003 + 1 + 0.2527967095375061 + <_> + + + + <_>10 9 7 10 -1. + <_>10 14 7 5 2. + 0 + -0.1288381963968277 + 0.1393000930547714 + 0.5254514813423157 + <_> + + <_> + + + + <_>3 9 7 10 -1. + <_>3 14 7 5 2. + 0 + 7.9412180930376053e-003 + 1 + 0.2487729042768478 + <_> + + + + <_>7 5 1 14 -1. + <_>7 12 1 7 2. + 0 + -0.0126617299392819 + 0.2710700035095215 + 0.6618837714195252 + <_> + + <_> + + + + <_>13 14 1 6 -1. + <_>13 16 1 2 3. + 0 + 3.0146789868013002e-005 + 0.3812825977802277 + 1 + <_> + + + + <_>14 12 3 6 -1. + <_>14 14 3 2 3. + 0 + -0.0163301602005959 + 0.2326432019472122 + 0.5263010859489441 + <_> + + <_> + + + + <_>6 14 1 6 -1. + <_>6 16 1 2 3. + 0 + 1.4622770322603174e-005 + 0.4293332099914551 + 1 + <_> + + + + <_>3 12 3 6 -1. + <_>3 14 3 2 3. + 0 + -0.0208586603403091 + 0.1600403934717178 + 0.6782314777374268 + <_> + + <_> + + + + <_>8 13 5 3 -1. + <_>8 14 5 1 3. + 0 + 2.8194559272378683e-003 + 1 + 0.6679294109344482 + <_> + + + + <_>9 14 2 3 -1. + <_>9 15 2 1 3. + 0 + 3.7899368908256292e-003 + 0.4587705135345459 + 0.7176238894462585 + <_> + + <_> + + + + <_>5 1 10 8 -1. + <_>5 1 5 4 2. + <_>10 5 5 4 2. + 0 + 0.0353446416556835 + 1 + 0.1864075064659119 + <_> + + + + <_>6 4 5 4 -1. + <_>6 6 5 2 2. + 0 + -1.1571600334718823e-003 + 0.5538259744644165 + 0.3150450885295868 + <_> + + <_> + + + + <_>1 10 18 1 -1. + <_>7 10 6 1 3. + 0 + -5.8742752298712730e-003 + 0.2828791141510010 + 1 + <_> + + + + <_>11 10 4 3 -1. + <_>11 10 2 3 2. + 0 + -1.5201780115603469e-005 + 0.5870224237442017 + 0.3704823851585388 + <_> + + <_> + + + + <_>5 11 6 1 -1. + <_>7 11 2 1 3. + 0 + -2.2681879636365920e-004 + 1 + 0.4218930900096893 + <_> + + + + <_>3 13 2 3 -1. + <_>3 14 2 1 3. + 0 + 3.7845689803361893e-003 + 0.6667001247406006 + 0.2461182028055191 + <_> + + <_> + + + + <_>12 12 3 4 -1. + <_>12 14 3 2 2. + 0 + -8.5295992903411388e-005 + 1 + 0.3557587862014771 + <_> + + + + <_>11 10 5 6 -1. + <_>11 12 5 2 3. + 0 + -0.0443948917090893 + 0.1665547043085098 + 0.5234848856925964 + <_> + + <_> + + + + <_>0 8 16 2 -1. + <_>0 9 16 1 2. + 0 + 1.0126030538231134e-003 + 0.2884612977504730 + 1 + <_> + + + + <_>2 1 3 4 -1. + <_>2 3 3 2 2. + 0 + -7.6327780261635780e-003 + 0.2969340085983276 + 0.6080111265182495 + <_> + + <_> + + + + <_>9 7 3 3 -1. + <_>10 7 1 3 3. + 0 + 4.0330411866307259e-003 + 0.4536390006542206 + 1 + <_> + + + + <_>5 6 12 6 -1. + <_>9 6 4 6 3. + 0 + 0.1367668956518173 + 0.5177264213562012 + 0.1449182033538818 + <_> + + <_> + + + + <_>8 7 3 3 -1. + <_>9 7 1 3 3. + 0 + -5.0060478970408440e-003 + 0.7616909742355347 + 1 + <_> + + + + <_>3 6 12 6 -1. + <_>7 6 4 6 3. + 0 + -0.0124758398160338 + 0.2159706056118012 + 0.5460187792778015 + <_> + + <_> + + + + <_>10 5 6 5 -1. + <_>12 5 2 5 3. + 0 + -9.4012258341535926e-004 + 1 + 0.3926295936107636 + <_> + + + + <_>5 7 10 2 -1. + <_>5 7 5 2 2. + 0 + -0.0121919801458716 + 0.3478881120681763 + 0.5542662739753723 + <_> + + <_> + + + + <_>4 5 6 5 -1. + <_>6 5 2 5 3. + 0 + -5.4959481349214911e-004 + 0.6064276099205017 + 1 + <_> + + + + <_>9 3 2 10 -1. + <_>9 8 2 5 2. + 0 + -2.1802430273965001e-004 + 0.5697407126426697 + 0.1779713928699493 + <_> + + <_> + + + + <_>3 1 16 2 -1. + <_>11 1 8 1 2. + <_>3 2 8 1 2. + 0 + 6.9115799851715565e-003 + 0.5379372239112854 + 1 + <_> + + + + <_>9 9 3 2 -1. + <_>9 10 3 1 2. + 0 + -9.7631698008626699e-004 + 0.3327839076519013 + 0.5461531281471252 + <_> + + <_> + + + + <_>1 1 16 2 -1. + <_>1 1 8 1 2. + <_>9 2 8 1 2. + 0 + -8.7870173156261444e-003 + 0.2116160988807678 + 1 + <_> + + + + <_>8 14 1 3 -1. + <_>8 15 1 1 3. + 0 + -1.6761029837653041e-003 + 0.6635823249816895 + 0.4365859031677246 + <_> + + <_> + + + + <_>4 5 12 10 -1. + <_>10 5 6 5 2. + <_>4 10 6 5 2. + 0 + -0.0556949488818645 + 1 + 0.5387424826622009 + <_> + + + + <_>7 13 6 6 -1. + <_>10 13 3 3 2. + <_>7 16 3 3 2. + 0 + -0.0198443792760372 + 0.1602804958820343 + 0.5330458879470825 + <_> + + <_> + + + + <_>8 9 3 2 -1. + <_>8 10 3 1 2. + 0 + -7.4751611100509763e-004 + 0.2917476892471314 + 1 + <_> + + + + <_>7 2 6 4 -1. + <_>9 2 2 4 3. + 0 + 0.0230328906327486 + 0.5608124136924744 + 0.1997981071472168 + <_> + + <_> + + + + <_>6 6 9 3 -1. + <_>6 7 9 1 3. + 0 + -3.0700280331075191e-003 + 1 + 0.3938314020633698 + <_> + + + + <_>10 7 6 1 -1. + <_>12 7 2 1 3. + 0 + -1.1636839481070638e-003 + 0.5757436156272888 + 0.4239456951618195 + <_> + + <_> + + + + <_>0 0 18 6 -1. + <_>6 0 6 6 3. + 0 + 0.2246433943510056 + 1 + 0.7676553130149841 + <_> + + + + <_>6 10 2 6 -1. + <_>6 13 2 3 2. + 0 + 1.4412109740078449e-003 + 0.5353866219520569 + 0.2514776885509491 + <_> + + <_> + + + + <_>11 12 3 6 -1. + <_>11 15 3 3 2. + 0 + -0.0300112497061491 + 0.2364903986454010 + 1 + <_> + + + + <_>4 4 12 12 -1. + <_>10 4 6 6 2. + <_>4 10 6 6 2. + 0 + -0.0530789606273174 + 0.2385863959789276 + 0.5414664745330811 + <_> + + <_> + + + + <_>1 2 3 6 -1. + <_>2 2 1 6 3. + 0 + 2.0800929050892591e-003 + 1 + 0.6511614918708801 + <_> + + + + <_>1 5 3 7 -1. + <_>2 5 1 7 3. + 0 + -4.0738182142376900e-003 + 0.6030414104461670 + 0.3587701022624970 + <_> + + <_> + + + + <_>4 13 12 4 -1. + <_>10 13 6 2 2. + <_>4 15 6 2 2. + 0 + -0.0195293705910444 + 1 + 0.5423592925071716 + <_> + + + + <_>3 3 17 12 -1. + <_>3 9 17 6 2. + 0 + -0.0533094704151154 + 0.2360953986644745 + 0.5401757955551148 + <_> + + <_> + + + + <_>3 3 14 12 -1. + <_>3 3 7 6 2. + <_>10 9 7 6 2. + 0 + -0.0348495617508888 + 0.2836985886096954 + 1 + <_> + + + + <_>2 11 16 9 -1. + <_>2 14 16 3 3. + 0 + -0.1265845000743866 + 0.1813516020774841 + 0.5421046018600464 + <_> + + <_> + + + + <_>9 14 3 6 -1. + <_>9 17 3 3 2. + 0 + 7.3325118137290701e-006 + 0.3980365991592407 + 1 + <_> + + + + <_>8 14 4 6 -1. + <_>10 14 2 3 2. + <_>8 17 2 3 2. + 0 + -0.0118438703939319 + 0.2616384923458099 + 0.5237730145454407 + <_> + + <_> + + + + <_>6 2 6 1 -1. + <_>8 2 2 1 3. + 0 + -4.8470678739249706e-003 + 0.2438108026981354 + 1 + <_> + + + + <_>9 5 2 5 -1. + <_>10 5 1 5 2. + 0 + 8.1693977117538452e-003 + 0.5327146053314209 + 0.8190376758575440 + <_> + + <_> + + + + <_>9 8 3 5 -1. + <_>10 8 1 5 3. + 0 + -6.4716790802776814e-003 + 1 + 0.4679693877696991 + <_> + + + + <_>9 12 6 1 -1. + <_>9 12 3 1 2. + 0 + -1.5188479665084742e-005 + 0.5563911795616150 + 0.4367586076259613 + <_> + + <_> + + + + <_>8 8 3 5 -1. + <_>9 8 1 5 3. + 0 + 3.0696711037307978e-003 + 1 + 0.6664348840713501 + <_> + + + + <_>6 10 4 3 -1. + <_>8 10 2 3 2. + 0 + -1.6296720423270017e-004 + 0.5594611167907715 + 0.3042711913585663 + 14.5467500686645510 + 5 + -1 + <_> + + + <_> + + <_> + + + + <_>0 4 20 6 -1. + <_>0 6 20 2 3. + 0 + -9.8275858908891678e-003 + 1 + 0.2116018980741501 + <_> + + + + <_>1 3 8 6 -1. + <_>1 3 4 3 2. + <_>5 6 4 3 2. + 0 + -4.1693858802318573e-003 + 0.6924685239791870 + 0.3043777048587799 + <_> + + <_> + + + + <_>7 15 6 4 -1. + <_>7 17 6 2 2. + 0 + 3.5341319744475186e-004 + 0.3183285892009735 + 1 + <_> + + + + <_>3 10 14 10 -1. + <_>3 15 14 5 2. + 0 + 4.8054549843072891e-003 + 0.5456559062004089 + 0.2522268891334534 + <_> + + <_> + + + + <_>6 4 4 4 -1. + <_>8 4 2 4 2. + 0 + 2.1071180526632816e-004 + 0.2902618050575256 + 1 + <_> + + + + <_>0 4 20 10 -1. + <_>0 9 20 5 2. + 0 + -2.8318869881331921e-003 + 0.3130455911159515 + 0.6884937286376953 + <_> + + <_> + + + + <_>9 4 2 14 -1. + <_>9 11 2 7 2. + 0 + -7.5633679443853907e-006 + 1 + 0.2962465882301331 + <_> + + + + <_>2 0 16 4 -1. + <_>2 2 16 2 2. + 0 + -8.2888139877468348e-004 + 0.3099626004695892 + 0.5752515196800232 + <_> + + <_> + + + + <_>4 12 6 8 -1. + <_>4 12 3 4 2. + <_>7 16 3 4 2. + 0 + 1.6209259629249573e-003 + 0.3993195891380310 + 1 + <_> + + + + <_>0 5 6 7 -1. + <_>3 5 3 7 2. + 0 + 9.1338958591222763e-003 + 0.4827372133731842 + 0.7537832856178284 + <_> + + <_> + + + + <_>10 7 10 4 -1. + <_>15 7 5 2 2. + <_>10 9 5 2 2. + 0 + -4.1212290525436401e-003 + 0.2616927027702332 + 1 + <_> + + + + <_>5 8 12 1 -1. + <_>9 8 4 1 3. + 0 + -2.5447290390729904e-003 + 0.3108702898025513 + 0.5491235852241516 + <_> + + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + -6.2652782071381807e-004 + 0.3239691853523254 + 1 + <_> + + + + <_>9 4 2 4 -1. + <_>9 6 2 2 2. + 0 + -3.6596331483451650e-005 + 0.6517410874366760 + 0.4178912043571472 + <_> + + <_> + + + + <_>9 6 3 6 -1. + <_>10 6 1 6 3. + 0 + 0.0138827199116349 + 1 + 0.6771203875541687 + <_> + + + + <_>12 7 6 4 -1. + <_>15 7 3 2 2. + <_>12 9 3 2 2. + 0 + 1.0493700392544270e-003 + 0.4159511029720306 + 0.5652891993522644 + <_> + + <_> + + + + <_>8 6 3 6 -1. + <_>9 6 1 6 3. + 0 + 0.0182153601199389 + 1 + 0.7689601182937622 + <_> + + + + <_>1 6 18 6 -1. + <_>1 6 9 3 2. + <_>10 9 9 3 2. + 0 + -0.0113345803692937 + 0.2873323857784271 + 0.4988932907581329 + <_> + + <_> + + + + <_>9 1 3 3 -1. + <_>10 1 1 3 3. + 0 + -4.1097560897469521e-003 + 1 + 0.5463008284568787 + <_> + + + + <_>10 8 5 2 -1. + <_>10 9 5 1 2. + 0 + 4.2612891411408782e-004 + 0.3631235063076019 + 0.5512552261352539 + <_> + + <_> + + + + <_>8 1 3 3 -1. + <_>9 1 1 3 3. + 0 + 6.0301548801362514e-003 + 1 + 0.1143767014145851 + <_> + + + + <_>5 8 5 2 -1. + <_>5 9 5 1 2. + 0 + 3.3587709185667336e-004 + 0.2891078889369965 + 0.5447341799736023 + <_> + + <_> + + + + <_>8 6 8 8 -1. + <_>12 6 4 4 2. + <_>8 10 4 4 2. + 0 + 6.2279507983475924e-004 + 1 + 0.3023431897163391 + <_> + + + + <_>5 7 10 2 -1. + <_>5 7 5 2 2. + 0 + -0.0258371196687222 + 0.2167005985975266 + 0.5278152823448181 + <_> + + <_> + + + + <_>4 5 12 10 -1. + <_>4 5 6 5 2. + <_>10 10 6 5 2. + 0 + 0.0217749103903770 + 1 + 0.3254834115505219 + <_> + + + + <_>5 5 2 3 -1. + <_>5 6 2 1 3. + 0 + 1.7682299949228764e-003 + 0.5263050794601440 + 0.7526329159736633 + <_> + + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + -0.0137938102707267 + 0.7410330176353455 + 1 + <_> + + + + <_>9 14 3 3 -1. + <_>9 15 3 1 3. + 0 + -5.0852829590439796e-003 + 0.6836609840393066 + 0.4579071104526520 + <_> + + <_> + + + + <_>8 14 3 3 -1. + <_>8 15 3 1 3. + 0 + 6.1795017682015896e-003 + 1 + 0.7449936270713806 + <_> + + + + <_>1 10 8 9 -1. + <_>1 13 8 3 3. + 0 + 0.0100303199142218 + 0.4860779941082001 + 0.2361457049846649 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 8 2 1 3. + 0 + -6.4201927743852139e-003 + 0.1467327028512955 + 1 + <_> + + + + <_>12 3 3 3 -1. + <_>13 3 1 3 3. + 0 + -5.6961281225085258e-003 + 0.2347819954156876 + 0.5323377251625061 + <_> + + <_> + + + + <_>5 3 3 3 -1. + <_>6 3 1 3 3. + 0 + -7.1498160250484943e-003 + 0.1477057039737701 + 1 + <_> + + + + <_>5 6 2 12 -1. + <_>5 10 2 4 3. + 0 + 2.4450740311294794e-003 + 0.3498533964157105 + 0.5803561806678772 + <_> + + <_> + + + + <_>1 11 18 4 -1. + <_>10 11 9 2 2. + <_>1 13 9 2 2. + 0 + -0.0375034101307392 + 1 + 0.5259550809860230 + <_> + + + + <_>7 12 6 2 -1. + <_>7 13 6 1 2. + 0 + 4.7799441381357610e-004 + 0.4362882971763611 + 0.6208922863006592 + <_> + + <_> + + + + <_>6 0 3 6 -1. + <_>7 0 1 6 3. + 0 + -7.0806080475449562e-003 + 0.2039460986852646 + 1 + <_> + + + + <_>0 11 18 4 -1. + <_>0 11 9 2 2. + <_>9 13 9 2 2. + 0 + 0.0328180007636547 + 0.5198358893394470 + 0.1371196061372757 + <_> + + <_> + + + + <_>7 12 6 2 -1. + <_>7 13 6 1 2. + 0 + 6.5188988810405135e-004 + 1 + 0.6323429942131043 + <_> + + + + <_>9 12 3 3 -1. + <_>9 13 3 1 3. + 0 + 4.6485587954521179e-003 + 0.4720163047313690 + 0.6567087173461914 + <_> + + <_> + + + + <_>9 12 2 3 -1. + <_>9 13 2 1 3. + 0 + -1.9827929791063070e-003 + 0.6053060293197632 + 1 + <_> + + + + <_>8 11 4 3 -1. + <_>8 12 4 1 3. + 0 + -1.6011310508474708e-003 + 0.5090519189834595 + 0.3116933107376099 + <_> + + <_> + + + + <_>13 3 4 2 -1. + <_>13 4 4 1 2. + 0 + -3.0539939180016518e-003 + 0.3429804146289825 + 1 + <_> + + + + <_>4 0 12 2 -1. + <_>4 1 12 1 2. + 0 + 4.3212040327489376e-004 + 0.3838402926921845 + 0.5775598287582398 + <_> + + <_> + + + + <_>6 9 8 8 -1. + <_>6 9 4 4 2. + <_>10 13 4 4 2. + 0 + -0.0274521205574274 + 0.2143469005823135 + 1 + <_> + + + + <_>1 11 6 2 -1. + <_>1 12 6 1 2. + 0 + 9.3099439982324839e-004 + 0.5952966213226318 + 0.3760158121585846 + <_> + + <_> + + + + <_>2 5 18 8 -1. + <_>11 5 9 4 2. + <_>2 9 9 4 2. + 0 + 6.7144189961254597e-003 + 0.5692626833915710 + 1 + <_> + + + + <_>7 1 6 10 -1. + <_>7 6 6 5 2. + 0 + -3.3701690845191479e-003 + 0.5784304141998291 + 0.3974282145500183 + <_> + + <_> + + + + <_>0 3 3 6 -1. + <_>0 5 3 2 3. + 0 + -0.0189039595425129 + 0.1818892955780029 + 1 + <_> + + + + <_>4 5 4 3 -1. + <_>4 6 4 1 3. + 0 + -6.5850871615111828e-003 + 0.6849110126495361 + 0.4351584017276764 + <_> + + <_> + + + + <_>19 3 1 6 -1. + <_>19 5 1 2 3. + 0 + 5.8810501359403133e-003 + 1 + 0.2726660966873169 + <_> + + + + <_>6 15 8 2 -1. + <_>6 16 8 1 2. + 0 + 8.0092082498595119e-004 + 0.4236431121826172 + 0.5844675898551941 + <_> + + <_> + + + + <_>0 3 1 6 -1. + <_>0 5 1 2 3. + 0 + 1.8510579830035567e-003 + 1 + 0.3371320962905884 + <_> + + + + <_>5 5 3 3 -1. + <_>5 6 3 1 3. + 0 + 6.3273650594055653e-003 + 0.5270221829414368 + 0.8053650856018066 + <_> + + <_> + + + + <_>8 8 4 3 -1. + <_>8 9 4 1 3. + 0 + -3.3820930402725935e-003 + 0.2866018116474152 + 1 + <_> + + + + <_>10 6 6 3 -1. + <_>12 6 2 3 3. + 0 + -1.9292969955131412e-003 + 0.5888946056365967 + 0.3895787000656128 + <_> + + <_> + + + + <_>8 13 2 6 -1. + <_>8 16 2 3 2. + 0 + 0.0149952201172709 + 1 + 0.2177816927433014 + <_> + + + + <_>9 11 2 8 -1. + <_>9 15 2 4 2. + 0 + -0.0263307504355907 + 0.1775317043066025 + 0.5671470165252686 + <_> + + <_> + + + + <_>10 6 6 3 -1. + <_>12 6 2 3 3. + 0 + -4.1734222322702408e-003 + 1 + 0.4652962088584900 + <_> + + + + <_>5 15 15 5 -1. + <_>10 15 5 5 3. + 0 + 0.0272683501243591 + 0.4768311083316803 + 0.5695238709449768 + <_> + + <_> + + + + <_>2 14 2 2 -1. + <_>2 15 2 1 2. + 0 + 9.8880263976752758e-004 + 1 + 0.3397401869297028 + <_> + + + + <_>4 7 6 2 -1. + <_>6 7 2 2 3. + 0 + -1.0528849670663476e-003 + 0.6250041127204895 + 0.4288412034511566 + <_> + + <_> + + + + <_>8 3 6 1 -1. + <_>10 3 2 1 3. + 0 + 5.2288072183728218e-003 + 0.5347762107849121 + 1 + <_> + + + + <_>1 0 18 12 -1. + <_>7 0 6 12 3. + 0 + 0.0303954593837261 + 0.4115518927574158 + 0.5660753846168518 + <_> + + <_> + + + + <_>0 14 8 6 -1. + <_>4 14 4 6 2. + 0 + -0.0791139304637909 + 0.7881323099136353 + 1 + <_> + + + + <_>0 15 15 5 -1. + <_>5 15 5 5 3. + 0 + 0.0182316694408655 + 0.3604339957237244 + 0.5569505095481873 + <_> + + <_> + + + + <_>8 3 6 1 -1. + <_>10 3 2 1 3. + 0 + 5.2288072183728218e-003 + 0.5416644215583801 + 1 + <_> + + + + <_>11 11 3 6 -1. + <_>11 14 3 3 2. + 0 + 4.3922828626818955e-004 + 0.5507156848907471 + 0.3882277011871338 + <_> + + <_> + + + + <_>6 3 6 1 -1. + <_>8 3 2 1 3. + 0 + -8.6501962505280972e-004 + 0.3185850977897644 + 1 + <_> + + + + <_>6 11 3 6 -1. + <_>6 14 3 3 2. + 0 + 1.0326979681849480e-003 + 0.5578364133834839 + 0.3219245970249176 + <_> + + <_> + + + + <_>9 6 3 4 -1. + <_>10 6 1 4 3. + 0 + -7.2997747920453548e-003 + 0.7073233127593994 + 1 + <_> + + + + <_>12 10 4 7 -1. + <_>12 10 2 7 2. + 0 + -9.3629042385146022e-004 + 0.5558015704154968 + 0.4613842070102692 + <_> + + <_> + + + + <_>8 6 3 4 -1. + <_>9 6 1 4 3. + 0 + -6.0483231209218502e-003 + 0.6869289875030518 + 1 + <_> + + + + <_>4 6 4 7 -1. + <_>6 6 2 7 2. + 0 + 6.7529221996665001e-003 + 0.4870317876338959 + 0.2650370895862579 + <_> + + <_> + + + + <_>10 3 4 12 -1. + <_>10 3 2 12 2. + 0 + 0.0530780293047428 + 0.5281515121459961 + 1 + <_> + + + + <_>10 8 3 4 -1. + <_>11 8 1 4 3. + 0 + -1.0225810110569000e-003 + 0.6085882186889648 + 0.4304867982864380 + <_> + + <_> + + + + <_>1 0 18 14 -1. + <_>7 0 6 14 3. + 0 + 0.0312706492841244 + 1 + 0.5445832014083862 + <_> + + + + <_>2 8 6 11 -1. + <_>5 8 3 11 2. + 0 + -6.3522169366478920e-003 + 0.5328335762023926 + 0.2364324033260346 + 18.5722503662109380 + 6 + -1 + <_> + + + <_> + + <_> + + + + <_>1 4 15 4 -1. + <_>1 6 15 2 2. + 0 + -6.2215630896389484e-003 + 1 + 0.2625581026077271 + <_> + + + + <_>5 5 10 8 -1. + <_>5 9 10 4 2. + 0 + 2.1097389981150627e-003 + 0.1564992964267731 + 0.6792883276939392 + <_> + + <_> + + + + <_>14 2 6 8 -1. + <_>14 2 3 8 2. + 0 + 0.0108458595350385 + 0.3485808968544006 + 1 + <_> + + + + <_>11 6 6 14 -1. + <_>14 6 3 7 2. + <_>11 13 3 7 2. + 0 + 6.4230401767417789e-004 + 0.3698255121707916 + 0.5921658277511597 + <_> + + <_> + + + + <_>9 5 2 12 -1. + <_>9 11 2 6 2. + 0 + 7.3311722371727228e-004 + 1 + 0.3007084131240845 + <_> + + + + <_>3 7 4 6 -1. + <_>3 9 4 2 3. + 0 + 1.0134200565516949e-003 + 0.3624922931194305 + 0.7072426080703735 + <_> + + <_> + + + + <_>14 3 6 6 -1. + <_>14 3 3 6 2. + 0 + 0.0110935596749187 + 0.4416702091693878 + 1 + <_> + + + + <_>15 2 4 4 -1. + <_>15 4 4 2 2. + 0 + -7.9127531498670578e-003 + 0.3028708100318909 + 0.5417376160621643 + <_> + + <_> + + + + <_>0 2 6 7 -1. + <_>3 2 3 7 2. + 0 + 0.0129053099080920 + 0.4374504089355469 + 1 + <_> + + + + <_>3 6 6 14 -1. + <_>3 6 3 7 2. + <_>6 13 3 7 2. + 0 + -4.2430912144482136e-003 + 0.4401589930057526 + 0.7565190792083740 + <_> + + <_> + + + + <_>4 6 16 8 -1. + <_>4 10 16 4 2. + 0 + -2.1304309484548867e-004 + 0.2310786992311478 + 1 + <_> + + + + <_>10 12 2 8 -1. + <_>10 16 2 4 2. + 0 + -2.2308640182018280e-003 + 0.3568195998668671 + 0.5749999284744263 + <_> + + <_> + + + + <_>7 0 6 20 -1. + <_>9 0 2 20 3. + 0 + 2.6400520000606775e-003 + 0.3593688905239105 + 1 + <_> + + + + <_>1 7 16 12 -1. + <_>1 7 8 6 2. + <_>9 13 8 6 2. + 0 + 0.0751010328531265 + 0.6363567709922791 + 0.2327028959989548 + <_> + + <_> + + + + <_>9 11 3 3 -1. + <_>9 12 3 1 3. + 0 + -7.7012968249619007e-003 + 0.7074623703956604 + 1 + <_> + + + + <_>11 9 4 5 -1. + <_>11 9 2 5 2. + 0 + 1.5588370151817799e-003 + 0.5700237154960632 + 0.3590450882911682 + <_> + + <_> + + + + <_>3 3 1 2 -1. + <_>3 4 1 1 2. + 0 + -4.7687938786111772e-004 + 0.2805441021919251 + 1 + <_> + + + + <_>7 17 5 3 -1. + <_>7 18 5 1 3. + 0 + 8.4234727546572685e-004 + 0.4125418961048126 + 0.6177995800971985 + <_> + + <_> + + + + <_>8 12 4 8 -1. + <_>10 12 2 4 2. + <_>8 16 2 4 2. + 0 + -0.0128251099959016 + 1 + 0.5403078198432922 + <_> + + + + <_>7 4 10 12 -1. + <_>12 4 5 6 2. + <_>7 10 5 6 2. + 0 + -6.5156567143276334e-004 + 0.5633643865585327 + 0.3356539011001587 + <_> + + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + -0.0120061598718166 + 0.7109510898590088 + 1 + <_> + + + + <_>5 9 4 5 -1. + <_>7 9 2 5 2. + 0 + 1.3213419588282704e-003 + 0.4903850853443146 + 0.2824583053588867 + <_> + + <_> + + + + <_>9 9 8 2 -1. + <_>9 9 4 2 2. + 0 + -0.0203074403107166 + 0.1891369968652725 + 1 + <_> + + + + <_>14 15 5 2 -1. + <_>14 16 5 1 2. + 0 + 4.0180929936468601e-003 + 0.5377966165542603 + 0.3119494915008545 + <_> + + <_> + + + + <_>9 14 2 3 -1. + <_>9 15 2 1 3. + 0 + 4.5315311290323734e-003 + 1 + 0.7206758260726929 + <_> + + + + <_>1 7 8 4 -1. + <_>1 7 4 2 2. + <_>5 9 4 2 2. + 0 + -4.4381739571690559e-003 + 0.1854667961597443 + 0.4981732964515686 + <_> + + <_> + + + + <_>19 3 1 2 -1. + <_>19 4 1 1 2. + 0 + 1.5692010056227446e-003 + 1 + 0.2638274133205414 + <_> + + + + <_>9 12 2 3 -1. + <_>9 13 2 1 3. + 0 + -4.9516442231833935e-003 + 0.6871067285537720 + 0.4714686870574951 + <_> + + <_> + + + + <_>3 14 14 4 -1. + <_>3 14 7 2 2. + <_>10 16 7 2 2. + 0 + -0.0274296794086695 + 0.1548285037279129 + 1 + <_> + + + + <_>5 0 10 2 -1. + <_>5 1 10 1 2. + 0 + 1.4181969454512000e-003 + 0.4376842975616455 + 0.6327368021011353 + <_> + + <_> + + + + <_>11 14 4 6 -1. + <_>11 16 4 2 3. + 0 + -0.0130789401009679 + 0.3166814148426056 + 1 + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + -3.5092779435217381e-003 + 0.6199743747711182 + 0.4379687011241913 + <_> + + <_> + + + + <_>7 13 6 6 -1. + <_>7 13 3 3 2. + <_>10 16 3 3 2. + 0 + 0.0189207307994366 + 1 + 0.1470714062452316 + <_> + + + + <_>0 2 1 6 -1. + <_>0 4 1 2 3. + 0 + 2.1683350205421448e-003 + 0.5809459090232849 + 0.3431949019432068 + <_> + + <_> + + + + <_>6 7 8 2 -1. + <_>6 8 8 1 2. + 0 + 1.6401590546593070e-003 + 0.3959457874298096 + 1 + <_> + + + + <_>9 7 6 1 -1. + <_>9 7 3 1 2. + 0 + 1.4005920093040913e-004 + 0.3240025043487549 + 0.5646647214889526 + <_> + + <_> + + + + <_>7 1 6 10 -1. + <_>7 6 6 5 2. + 0 + -3.3137591090053320e-003 + 1 + 0.4274528026580811 + <_> + + + + <_>0 2 6 2 -1. + <_>0 3 6 1 2. + 0 + -2.9459029901772738e-003 + 0.3341667950153351 + 0.6627960205078125 + <_> + + <_> + + + + <_>11 4 2 4 -1. + <_>11 4 1 4 2. + 0 + 1.3612229668069631e-004 + 0.4046927988529205 + 1 + <_> + + + + <_>11 10 3 6 -1. + <_>11 13 3 3 2. + 0 + 6.0512032359838486e-004 + 0.5484058260917664 + 0.3569940924644470 + <_> + + <_> + + + + <_>3 9 8 2 -1. + <_>7 9 4 2 2. + 0 + -0.0175139904022217 + 0.1824150979518890 + 1 + <_> + + + + <_>0 0 4 6 -1. + <_>2 0 2 6 2. + 0 + -0.0187350306659937 + 0.7971820235252380 + 0.5068569183349609 + <_> + + <_> + + + + <_>7 0 6 2 -1. + <_>9 0 2 2 3. + 0 + 0.0120656499639153 + 1 + 0.2167007029056549 + <_> + + + + <_>9 15 2 3 -1. + <_>9 16 2 1 3. + 0 + -2.6544178836047649e-003 + 0.6584178805351257 + 0.4628243148326874 + <_> + + <_> + + + + <_>3 12 1 2 -1. + <_>3 13 1 1 2. + 0 + 1.4501289697363973e-003 + 1 + 0.2090252041816711 + <_> + + + + <_>4 5 11 3 -1. + <_>4 6 11 1 3. + 0 + 0.0109540196135640 + 0.5112305283546448 + 0.7784575819969177 + <_> + + <_> + + + + <_>11 4 2 4 -1. + <_>11 4 1 4 2. + 0 + 0.0157717093825340 + 0.5132359266281128 + 1 + <_> + + + + <_>8 3 6 3 -1. + <_>10 3 2 3 3. + 0 + -0.0142526896670461 + 0.1742414981126785 + 0.5267148017883301 + <_> + + <_> + + + + <_>7 4 2 4 -1. + <_>8 4 1 4 2. + 0 + 3.0411860279855318e-005 + 0.3418447971343994 + 1 + <_> + + + + <_>6 3 6 3 -1. + <_>8 3 2 3 3. + 0 + 0.0234862994402647 + 0.5631265044212341 + 0.2006393969058991 + <_> + + <_> + + + + <_>11 4 4 3 -1. + <_>11 5 4 1 3. + 0 + 5.2205449901521206e-003 + 1 + 0.6249648928642273 + <_> + + + + <_>11 8 2 8 -1. + <_>11 12 2 4 2. + 0 + -0.0258124303072691 + 0.3203228116035461 + 0.5199329853057861 + <_> + + <_> + + + + <_>8 7 3 5 -1. + <_>9 7 1 5 3. + 0 + -1.9526650430634618e-003 + 0.6140705943107605 + 1 + <_> + + + + <_>9 7 2 5 -1. + <_>10 7 1 5 2. + 0 + -8.1470049917697906e-003 + 0.6592895984649658 + 0.3711124956607819 + <_> + + <_> + + + + <_>14 11 1 6 -1. + <_>14 13 1 2 3. + 0 + 3.2962448894977570e-003 + 1 + 0.2952111959457398 + <_> + + + + <_>8 8 4 3 -1. + <_>8 9 4 1 3. + 0 + -1.3961310032755136e-003 + 0.3320803940296173 + 0.5528414845466614 + <_> + + <_> + + + + <_>0 3 2 2 -1. + <_>0 4 2 1 2. + 0 + -4.1055441834032536e-003 + 0.1710550040006638 + 1 + <_> + + + + <_>4 14 5 6 -1. + <_>4 16 5 2 3. + 0 + -0.0108887795358896 + 0.3359434902667999 + 0.5674905180931091 + <_> + + <_> + + + + <_>11 4 4 3 -1. + <_>11 5 4 1 3. + 0 + -7.6768421567976475e-003 + 1 + 0.4773241877555847 + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + -9.7729787230491638e-003 + 0.8081045150756836 + 0.4845828115940094 + <_> + + <_> + + + + <_>5 4 4 3 -1. + <_>5 5 4 1 3. + 0 + 6.0439710505306721e-003 + 1 + 0.6784002184867859 + <_> + + + + <_>5 15 4 2 -1. + <_>7 15 2 2 2. + 0 + -4.6134641161188483e-004 + 0.5514639019966126 + 0.3642359972000122 + <_> + + <_> + + + + <_>15 1 5 9 -1. + <_>15 4 5 3 3. + 0 + 0.0579923614859581 + 1 + 0.1254435032606125 + <_> + + + + <_>9 10 3 3 -1. + <_>9 11 3 1 3. + 0 + 5.9384980704635382e-004 + 0.4424878954887390 + 0.5728461742401123 + <_> + + <_> + + + + <_>1 6 2 6 -1. + <_>1 8 2 2 3. + 0 + -6.2353480607271194e-003 + 0.2805041968822479 + 1 + <_> + + + + <_>2 4 8 15 -1. + <_>2 9 8 5 3. + 0 + -0.0127849299460649 + 0.1950912028551102 + 0.5652924776077271 + <_> + + <_> + + + + <_>9 12 3 2 -1. + <_>9 13 3 1 2. + 0 + 4.1973669431172311e-004 + 1 + 0.6166483759880066 + <_> + + + + <_>9 12 3 3 -1. + <_>9 13 3 1 3. + 0 + 8.0646801507100463e-004 + 0.4526579976081848 + 0.5944486856460571 + <_> + + <_> + + + + <_>7 6 3 5 -1. + <_>8 6 1 5 3. + 0 + -1.6339010326191783e-003 + 1 + 0.4086942076683044 + <_> + + + + <_>5 3 6 2 -1. + <_>7 3 2 2 3. + 0 + -4.8299999907612801e-003 + 0.2793526947498322 + 0.6444935202598572 + <_> + + <_> + + + + <_>6 1 8 10 -1. + <_>10 1 4 5 2. + <_>6 6 4 5 2. + 0 + -6.3992068171501160e-003 + 1 + 0.5671656131744385 + <_> + + + + <_>0 0 20 10 -1. + <_>10 0 10 5 2. + <_>0 5 10 5 2. + 0 + 0.1081919968128204 + 0.5311812162399292 + 0.2614356875419617 + <_> + + <_> + + + + <_>6 3 3 1 -1. + <_>7 3 1 1 3. + 0 + 6.5056560561060905e-004 + 1 + 0.2996774017810822 + <_> + + + + <_>0 2 6 8 -1. + <_>2 2 2 8 3. + 0 + 0.0206112507730722 + 0.4489943087100983 + 0.6888279914855957 + <_> + + <_> + + + + <_>11 10 3 4 -1. + <_>11 12 3 2 2. + 0 + -0.0251290500164032 + 1 + 0.5196864008903503 + <_> + + + + <_>12 6 3 8 -1. + <_>12 10 3 4 2. + 0 + 1.7922939732670784e-003 + 0.3466995954513550 + 0.5533587932586670 + <_> + + <_> + + + + <_>6 10 3 4 -1. + <_>6 12 3 2 2. + 0 + 1.5626220265403390e-003 + 1 + 0.3081440031528473 + <_> + + + + <_>5 6 3 8 -1. + <_>5 10 3 4 2. + 0 + -6.1898730928078294e-004 + 0.2693870961666107 + 0.5544489026069641 + <_> + + <_> + + + + <_>2 6 18 6 -1. + <_>11 6 9 3 2. + <_>2 9 9 3 2. + 0 + 4.8111421056091785e-003 + 0.5587847828865051 + 1 + <_> + + + + <_>7 14 7 3 -1. + <_>7 15 7 1 3. + 0 + 2.2484229411929846e-003 + 0.4672113060951233 + 0.6090825200080872 + <_> + + <_> + + + + <_>0 0 2 12 -1. + <_>1 0 1 12 2. + 0 + -0.0301472395658493 + 0.9027591943740845 + 1 + <_> + + + + <_>1 2 18 16 -1. + <_>1 10 18 8 2. + 0 + 0.2754867970943451 + 0.4719834923744202 + 0.2196920067071915 + <_> + + <_> + + + + <_>9 13 5 3 -1. + <_>9 14 5 1 3. + 0 + 3.6894630175083876e-003 + 1 + 0.6273009181022644 + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 7.2957701049745083e-003 + 0.4839217960834503 + 0.6909062266349793 + <_> + + <_> + + + + <_>0 6 18 6 -1. + <_>0 6 9 3 2. + <_>9 9 9 3 2. + 0 + -0.0562110692262650 + 0.1738487929105759 + 1 + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -2.6478560175746679e-003 + 0.6304144859313965 + 0.4474301934242249 + <_> + + <_> + + + + <_>17 4 1 3 -1. + <_>17 5 1 1 3. + 0 + -1.4534000074490905e-003 + 1 + 0.5302538275718689 + <_> + + + + <_>12 11 1 9 -1. + <_>12 14 1 3 3. + 0 + 2.8540920466184616e-003 + 0.5338397026062012 + 0.3796882927417755 + <_> + + <_> + + + + <_>2 4 1 3 -1. + <_>2 5 1 1 3. + 0 + 5.8243022067472339e-004 + 1 + 0.3269836902618408 + <_> + + + + <_>5 4 2 3 -1. + <_>5 5 2 1 3. + 0 + 9.2509482055902481e-004 + 0.4554812014102936 + 0.6358348131179810 + 21.5781192779541020 + 7 + -1 + <_> + + + <_> + + <_> + + + + <_>1 2 18 3 -1. + <_>7 2 6 3 3. + 0 + 0.0198064409196377 + 0.2809725105762482 + 1 + <_> + + + + <_>0 1 20 6 -1. + <_>0 3 20 2 3. + 0 + 7.0395611692219973e-004 + 0.3119826018810272 + 0.7090306282043457 + <_> + + <_> + + + + <_>7 5 6 3 -1. + <_>9 5 2 3 3. + 0 + 2.5563780218362808e-003 + 0.2981947958469391 + 1 + <_> + + + + <_>13 7 6 4 -1. + <_>16 7 3 2 2. + <_>13 9 3 2 2. + 0 + 1.0824160417541862e-003 + 0.3020560145378113 + 0.5808811187744141 + <_> + + <_> + + + + <_>3 1 4 10 -1. + <_>3 1 2 5 2. + <_>5 6 2 5 2. + 0 + -9.2893769033253193e-004 + 1 + 0.3738102912902832 + <_> + + + + <_>0 4 19 10 -1. + <_>0 9 19 5 2. + 0 + -0.0180097296833992 + 0.2163126021623612 + 0.6619253754615784 + <_> + + <_> + + + + <_>9 8 3 12 -1. + <_>9 12 3 4 3. + 0 + 2.3500190582126379e-003 + 1 + 0.2910403907299042 + <_> + + + + <_>11 18 5 2 -1. + <_>11 19 5 1 2. + 0 + 8.1822491483762860e-004 + 0.5578622817993164 + 0.3366627991199493 + <_> + + <_> + + + + <_>5 16 6 4 -1. + <_>5 16 3 2 2. + <_>8 18 3 2 2. + 0 + 6.2095321482047439e-004 + 0.4072425961494446 + 1 + <_> + + + + <_>5 18 3 2 -1. + <_>5 19 3 1 2. + 0 + 9.6780969761312008e-004 + 0.6859595775604248 + 0.3105461895465851 + <_> + + <_> + + + + <_>13 11 3 2 -1. + <_>13 12 3 1 2. + 0 + 4.8000211245380342e-004 + 1 + 0.3337332904338837 + <_> + + + + <_>8 5 8 4 -1. + <_>8 5 4 4 2. + 0 + 9.0538640506565571e-005 + 0.3370958864688873 + 0.5451210737228394 + <_> + + <_> + + + + <_>1 2 18 6 -1. + <_>1 2 9 3 2. + <_>10 5 9 3 2. + 0 + -0.0439147986471653 + 0.2625670135021210 + 1 + <_> + + + + <_>3 5 14 6 -1. + <_>3 7 14 2 3. + 0 + -5.6501338258385658e-003 + 0.6050462722778320 + 0.3232415020465851 + <_> + + <_> + + + + <_>18 1 2 6 -1. + <_>18 3 2 2 3. + 0 + 3.8661491125822067e-003 + 1 + 0.3262613117694855 + <_> + + + + <_>9 11 6 1 -1. + <_>11 11 2 1 3. + 0 + -6.3069426687434316e-005 + 0.5817307829856873 + 0.4164389967918396 + <_> + + <_> + + + + <_>0 2 6 11 -1. + <_>3 2 3 11 2. + 0 + 0.0525337383151054 + 1 + 0.7095398902893066 + <_> + + + + <_>4 12 2 3 -1. + <_>4 13 2 1 3. + 0 + 1.3818660518154502e-003 + 0.5292875766754150 + 0.2541388869285584 + <_> + + <_> + + + + <_>6 12 9 2 -1. + <_>9 12 3 2 3. + 0 + -8.9264067355543375e-004 + 1 + 0.4085341095924377 + <_> + + + + <_>9 4 6 15 -1. + <_>9 4 3 15 2. + 0 + 0.0855795070528984 + 0.5263236165046692 + 0.3003202974796295 + <_> + + <_> + + + + <_>5 11 6 1 -1. + <_>7 11 2 1 3. + 0 + -1.8343339615967125e-004 + 1 + 0.4029205143451691 + <_> + + + + <_>5 4 6 15 -1. + <_>8 4 3 15 2. + 0 + -9.7924815490841866e-003 + 0.3521319925785065 + 0.6664004921913147 + <_> + + <_> + + + + <_>14 12 6 7 -1. + <_>14 12 3 7 2. + 0 + 0.0144286202266812 + 0.4593566060066223 + 1 + <_> + + + + <_>18 3 2 9 -1. + <_>18 6 2 3 3. + 0 + -0.0456870011985302 + 0.1474756002426148 + 0.5178632140159607 + <_> + + <_> + + + + <_>8 1 3 1 -1. + <_>9 1 1 1 3. + 0 + -2.5763090234249830e-003 + 0.1837278008460999 + 1 + <_> + + + + <_>0 12 6 7 -1. + <_>3 12 3 7 2. + 0 + -0.0383018590509892 + 0.8082658052444458 + 0.5166687965393066 + <_> + + <_> + + + + <_>13 7 6 4 -1. + <_>16 7 3 2 2. + <_>13 9 3 2 2. + 0 + 2.8978290501981974e-003 + 0.4798013865947723 + 1 + <_> + + + + <_>8 0 10 2 -1. + <_>8 1 10 1 2. + 0 + -2.5165060069411993e-003 + 0.3346295952796936 + 0.5444449186325073 + <_> + + <_> + + + + <_>1 7 6 4 -1. + <_>1 7 3 2 2. + <_>4 9 3 2 2. + 0 + 5.6281982688233256e-004 + 0.3589026927947998 + 1 + <_> + + + + <_>1 2 3 3 -1. + <_>1 3 3 1 3. + 0 + 3.6684391088783741e-003 + 0.5983129739761353 + 0.2983964085578919 + <_> + + <_> + + + + <_>9 13 4 3 -1. + <_>9 14 4 1 3. + 0 + 2.1319789811968803e-003 + 1 + 0.6163223981857300 + <_> + + + + <_>12 13 7 2 -1. + <_>12 14 7 1 2. + 0 + 7.6037310063838959e-003 + 0.5217130184173584 + 0.2054159045219421 + <_> + + <_> + + + + <_>5 12 9 2 -1. + <_>8 12 3 2 3. + 0 + -1.1668079969240353e-004 + 1 + 0.3446668982505798 + <_> + + + + <_>6 10 4 8 -1. + <_>6 14 4 4 2. + 0 + 3.1659509986639023e-003 + 0.5597484707832336 + 0.2673786878585815 + <_> + + <_> + + + + <_>1 0 18 4 -1. + <_>7 0 6 4 3. + 0 + -0.0225694999098778 + 0.6900268197059631 + 1 + <_> + + + + <_>12 0 5 2 -1. + <_>12 1 5 1 2. + 0 + 2.7129601221531630e-004 + 0.4486638903617859 + 0.5508785247802734 + <_> + + <_> + + + + <_>7 7 1 12 -1. + <_>7 13 1 6 2. + 0 + -0.0154344597831368 + 0.2048323005437851 + 1 + <_> + + + + <_>6 2 3 4 -1. + <_>7 2 1 4 3. + 0 + -8.4861656650900841e-003 + 0.1254952996969223 + 0.5060356259346008 + <_> + + <_> + + + + <_>0 13 20 6 -1. + <_>0 15 20 2 3. + 0 + -0.1180747002363205 + 0.0676330626010895 + 1 + <_> + + + + <_>8 5 12 2 -1. + <_>14 5 6 1 2. + <_>8 6 6 1 2. + 0 + -1.2300079688429832e-003 + 0.5660700798034668 + 0.4292201101779938 + <_> + + <_> + + + + <_>8 14 2 3 -1. + <_>8 15 2 1 3. + 0 + -7.0290351286530495e-003 + 0.7136403918266296 + 1 + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + 8.9325206354260445e-003 + 0.4338876008987427 + 0.7060875296592712 + <_> + + <_> + + + + <_>12 13 7 6 -1. + <_>12 15 7 2 3. + 0 + -0.0477359816431999 + 1 + 0.5268685221672058 + <_> + + + + <_>6 0 8 12 -1. + <_>10 0 4 6 2. + <_>6 6 4 6 2. + 0 + -0.0441555790603161 + 0.2580580115318298 + 0.5406960844993591 + <_> + + <_> + + + + <_>0 15 9 4 -1. + <_>0 17 9 2 2. + 0 + -0.0259834807366133 + 0.1905054003000259 + 1 + <_> + + + + <_>9 0 2 5 -1. + <_>10 0 1 5 2. + 0 + -4.7885831445455551e-003 + 0.2551892995834351 + 0.5339077115058899 + <_> + + <_> + + + + <_>9 5 2 6 -1. + <_>9 5 1 6 2. + 0 + 6.7423451691865921e-003 + 0.4693309962749481 + 1 + <_> + + + + <_>17 2 3 6 -1. + <_>17 4 3 2 3. + 0 + 0.0116547504439950 + 0.5261964201927185 + 0.3145434856414795 + <_> + + <_> + + + + <_>3 11 2 3 -1. + <_>3 12 2 1 3. + 0 + -5.6982729583978653e-003 + 0.1756853014230728 + 1 + <_> + + + + <_>7 13 3 3 -1. + <_>7 14 3 1 3. + 0 + -7.2983349673449993e-003 + 0.7774729728698731 + 0.5124292969703674 + <_> + + <_> + + + + <_>14 12 5 3 -1. + <_>14 13 5 1 3. + 0 + 7.9091778025031090e-003 + 0.5284559726715088 + 1 + <_> + + + + <_>4 8 14 3 -1. + <_>4 9 14 1 3. + 0 + -1.5874979726504534e-004 + 0.3887802064418793 + 0.5501173734664917 + <_> + + <_> + + + + <_>1 12 5 3 -1. + <_>1 13 5 1 3. + 0 + -6.2235877849161625e-003 + 0.2489829063415527 + 1 + <_> + + + + <_>1 15 12 2 -1. + <_>1 15 6 1 2. + <_>7 16 6 1 2. + 0 + 1.3308860361576080e-003 + 0.4262146055698395 + 0.5935062170028687 + <_> + + <_> + + + + <_>12 11 4 2 -1. + <_>12 12 4 1 2. + 0 + 5.2055278792977333e-003 + 1 + 0.2545222938060761 + <_> + + + + <_>9 8 3 5 -1. + <_>10 8 1 5 3. + 0 + 0.0140651697292924 + 0.4851990044116974 + 0.7021418809890747 + <_> + + <_> + + + + <_>9 5 2 6 -1. + <_>10 5 1 6 2. + 0 + -6.7384149879217148e-003 + 0.7143270969390869 + 1 + <_> + + + + <_>0 2 3 6 -1. + <_>0 4 3 2 3. + 0 + 3.3406780567020178e-003 + 0.5175725221633911 + 0.2808643877506256 + <_> + + <_> + + + + <_>12 11 4 2 -1. + <_>12 12 4 1 2. + 0 + -0.0118806995451450 + 1 + 0.5173221826553345 + <_> + + + + <_>9 7 3 5 -1. + <_>10 7 1 5 3. + 0 + 1.4226379571482539e-003 + 0.4502865970134735 + 0.5795695185661316 + <_> + + <_> + + + + <_>4 11 4 2 -1. + <_>4 12 4 1 2. + 0 + 2.9858129564672709e-003 + 1 + 0.1915116012096405 + <_> + + + + <_>8 8 3 5 -1. + <_>9 8 1 5 3. + 0 + -2.0481580868363380e-003 + 0.6502432227134705 + 0.4559315145015717 + <_> + + <_> + + + + <_>9 3 3 1 -1. + <_>10 3 1 1 3. + 0 + 1.7122729914262891e-003 + 0.5376247167587280 + 1 + <_> + + + + <_>16 5 3 8 -1. + <_>17 5 1 8 3. + 0 + -0.0169808696955442 + 0.7056233286857605 + 0.4914605915546417 + <_> + + <_> + + + + <_>8 3 3 1 -1. + <_>9 3 1 1 3. + 0 + -1.1290470138192177e-003 + 0.2678706049919128 + 1 + <_> + + + + <_>1 5 3 8 -1. + <_>2 5 1 8 3. + 0 + 2.8620059601962566e-003 + 0.4410853981971741 + 0.6368319988250732 + <_> + + <_> + + + + <_>10 1 3 3 -1. + <_>11 1 1 3 3. + 0 + -3.8065758999437094e-003 + 0.2763563990592957 + 1 + <_> + + + + <_>17 5 2 4 -1. + <_>17 5 1 4 2. + 0 + 5.9090270660817623e-003 + 0.4867301881313324 + 0.6728776097297669 + <_> + + <_> + + + + <_>2 8 14 3 -1. + <_>2 9 14 1 3. + 0 + 1.1004370171576738e-003 + 0.4070514142513275 + 1 + <_> + + + + <_>9 7 1 3 -1. + <_>9 8 1 1 3. + 0 + -2.3396299220621586e-003 + 0.2604948878288269 + 0.6154860258102417 + <_> + + <_> + + + + <_>6 1 8 10 -1. + <_>6 6 8 5 2. + 0 + -3.6068160552531481e-003 + 0.5731999874114990 + 1 + <_> + + + + <_>13 0 6 8 -1. + <_>16 0 3 4 2. + <_>13 4 3 4 2. + 0 + 0.0408311896026134 + 0.4973376989364624 + 0.7387006878852844 + <_> + + <_> + + + + <_>1 5 2 4 -1. + <_>2 5 1 4 2. + 0 + -7.1082250215113163e-003 + 0.6984751224517822 + 1 + <_> + + + + <_>4 2 12 2 -1. + <_>4 3 12 1 2. + 0 + -9.3759730225428939e-004 + 0.2691167891025543 + 0.4741779863834381 + <_> + + <_> + + + + <_>8 8 4 4 -1. + <_>8 10 4 2 2. + 0 + -1.6740820137783885e-003 + 0.3551014065742493 + 1 + <_> + + + + <_>5 6 12 4 -1. + <_>9 6 4 4 3. + 0 + 0.0882877036929131 + 0.5244613885879517 + 0.2096650004386902 + <_> + + <_> + + + + <_>1 2 8 1 -1. + <_>5 2 4 1 2. + 0 + 8.2009629113599658e-004 + 0.4131096899509430 + 1 + <_> + + + + <_>1 1 6 10 -1. + <_>3 1 2 10 3. + 0 + -7.6624617213383317e-004 + 0.4620293080806732 + 0.6775410175323486 + <_> + + <_> + + + + <_>8 6 8 2 -1. + <_>8 6 4 2 2. + 0 + 6.5769668435677886e-004 + 1 + 0.5628275275230408 + <_> + + + + <_>10 7 6 6 -1. + <_>12 7 2 6 3. + 0 + -2.1304790861904621e-003 + 0.5576859712600708 + 0.4577650129795075 + <_> + + <_> + + + + <_>4 6 8 2 -1. + <_>8 6 4 2 2. + 0 + -3.7317050737328827e-004 + 1 + 0.4959256052970886 + <_> + + + + <_>4 7 6 6 -1. + <_>6 7 2 6 3. + 0 + -0.0111722303554416 + 0.5625635981559753 + 0.2047107964754105 + <_> + + <_> + + + + <_>3 14 16 4 -1. + <_>3 16 16 2 2. + 0 + 0.0434352196753025 + 1 + 0.2242148071527481 + <_> + + + + <_>8 12 4 2 -1. + <_>8 13 4 1 2. + 0 + 9.6736161503940821e-004 + 0.4533343911170960 + 0.6199932098388672 + <_> + + <_> + + + + <_>8 12 3 3 -1. + <_>8 13 3 1 3. + 0 + -3.1452889088541269e-003 + 0.6662756204605103 + 1 + <_> + + + + <_>5 12 6 1 -1. + <_>8 12 3 1 2. + 0 + 1.5233129961416125e-003 + 0.5007988214492798 + 0.2384992986917496 + <_> + + <_> + + + + <_>18 10 2 3 -1. + <_>18 11 2 1 3. + 0 + 2.0854279864579439e-003 + 1 + 0.3753500878810883 + <_> + + + + <_>16 8 4 6 -1. + <_>16 10 4 2 3. + 0 + 0.0360982008278370 + 0.5177171230316162 + 0.1634493023157120 + <_> + + <_> + + + + <_>8 3 2 1 -1. + <_>9 3 1 1 2. + 0 + 1.6179570229724050e-003 + 1 + 0.2587381899356842 + <_> + + + + <_>7 1 3 9 -1. + <_>8 1 1 9 3. + 0 + -6.2132300809025764e-004 + 0.6299533843994141 + 0.4658789932727814 + <_> + + <_> + + + + <_>5 11 11 6 -1. + <_>5 14 11 3 2. + 0 + 7.1878539165481925e-004 + 1 + 0.3354076147079468 + <_> + + + + <_>12 2 3 14 -1. + <_>12 9 3 7 2. + 0 + -0.0393395200371742 + 0.2154128998517990 + 0.5235713720321655 + <_> + + <_> + + + + <_>8 7 3 3 -1. + <_>9 7 1 3 3. + 0 + -1.0988829890266061e-003 + 0.6468896865844727 + 1 + <_> + + + + <_>3 5 12 5 -1. + <_>7 5 4 5 3. + 0 + 2.1191420964896679e-003 + 0.2893089056015015 + 0.5254815816879273 + 22.5852909088134770 + 8 + -1 + <_> + + + <_> + + <_> + + + + <_>1 2 6 3 -1. + <_>4 2 3 3 2. + 0 + 5.2359891124069691e-003 + 0.3299711048603058 + 1 + <_> + + + + <_>5 5 6 10 -1. + <_>5 5 3 5 2. + <_>8 10 3 5 2. + 0 + -2.2169889416545630e-003 + 0.7041593194007874 + 0.3235465884208679 + <_> + + <_> + + + + <_>16 18 2 2 -1. + <_>16 18 1 2 2. + 0 + -8.2303592935204506e-003 + 1 + 0.4961170852184296 + <_> + + + + <_>16 18 2 2 -1. + <_>16 18 1 2 2. + 0 + -8.2303592935204506e-003 + 0.7128043174743652 + 0.4961170852184296 + <_> + + <_> + + + + <_>8 4 2 5 -1. + <_>9 4 1 5 2. + 0 + 4.5343261444941163e-004 + 0.3208472132682800 + 1 + <_> + + + + <_>8 4 1 4 -1. + <_>8 6 1 2 2. + 0 + -4.1777061414904892e-004 + 0.6613916754722595 + 0.3551332950592041 + <_> + + <_> + + + + <_>7 15 12 4 -1. + <_>13 15 6 2 2. + <_>7 17 6 2 2. + 0 + 2.7823769487440586e-003 + 0.3710134923458099 + 1 + <_> + + + + <_>11 18 6 2 -1. + <_>11 19 6 1 2. + 0 + -6.0361868236213923e-005 + 0.5746393799781799 + 0.3894880115985870 + <_> + + <_> + + + + <_>7 7 4 10 -1. + <_>7 12 4 5 2. + 0 + 3.5061789676547050e-003 + 1 + 0.3054102957248688 + <_> + + + + <_>5 6 10 8 -1. + <_>5 10 10 4 2. + 0 + 1.7013119941111654e-004 + 0.2885577976703644 + 0.6487745046615601 + <_> + + <_> + + + + <_>11 1 6 12 -1. + <_>14 1 3 6 2. + <_>11 7 3 6 2. + 0 + -2.3378930054605007e-003 + 1 + 0.3174431025981903 + <_> + + + + <_>5 8 12 1 -1. + <_>9 8 4 1 3. + 0 + -2.1369170863181353e-003 + 0.3820919990539551 + 0.5232893228530884 + <_> + + <_> + + + + <_>4 7 3 6 -1. + <_>4 9 3 2 3. + 0 + 1.0250400518998504e-003 + 0.3622795045375824 + 1 + <_> + + + + <_>4 11 3 4 -1. + <_>4 13 3 2 2. + 0 + -4.4726220949087292e-005 + 0.6538959145545960 + 0.4003680944442749 + <_> + + <_> + + + + <_>14 16 2 2 -1. + <_>14 17 2 1 2. + 0 + 5.7102291611954570e-004 + 1 + 0.3893173038959503 + <_> + + + + <_>15 15 2 2 -1. + <_>15 16 2 1 2. + 0 + 5.7743012439459562e-004 + 0.5614532828330994 + 0.3687644004821777 + <_> + + <_> + + + + <_>7 12 6 2 -1. + <_>7 13 6 1 2. + 0 + 7.9692091094329953e-004 + 1 + 0.6443027853965759 + <_> + + + + <_>8 13 4 2 -1. + <_>8 14 4 1 2. + 0 + 3.5945948911830783e-004 + 0.3380852937698364 + 0.5824648141860962 + <_> + + <_> + + + + <_>11 1 6 12 -1. + <_>14 1 3 6 2. + <_>11 7 3 6 2. + 0 + 4.3973900028504431e-004 + 1 + 0.3938767015933991 + <_> + + + + <_>12 2 4 2 -1. + <_>12 3 4 1 2. + 0 + -8.9061429025605321e-004 + 0.3427971005439758 + 0.5515698790550232 + <_> + + <_> + + + + <_>3 10 12 6 -1. + <_>3 10 6 3 2. + <_>9 13 6 3 2. + 0 + 5.4110242053866386e-003 + 1 + 0.3803538084030151 + <_> + + + + <_>3 1 6 12 -1. + <_>3 1 3 6 2. + <_>6 7 3 6 2. + 0 + -8.5764907998964190e-004 + 0.6439505219459534 + 0.4168345928192139 + <_> + + <_> + + + + <_>16 6 4 14 -1. + <_>18 6 2 7 2. + <_>16 13 2 7 2. + 0 + -0.0220006499439478 + 0.6654601097106934 + 1 + <_> + + + + <_>5 1 10 8 -1. + <_>10 1 5 4 2. + <_>5 5 5 4 2. + 0 + -7.8731682151556015e-003 + 0.4182722866535187 + 0.5604724287986755 + <_> + + <_> + + + + <_>0 6 4 14 -1. + <_>0 6 2 7 2. + <_>2 13 2 7 2. + 0 + -0.0274444594979286 + 0.6586862802505493 + 1 + <_> + + + + <_>1 15 12 4 -1. + <_>1 15 6 2 2. + <_>7 17 6 2 2. + 0 + 1.9792269449681044e-003 + 0.3244912028312683 + 0.4882870018482208 + <_> + + <_> + + + + <_>10 17 3 3 -1. + <_>11 17 1 3 3. + 0 + -5.6783691979944706e-003 + 0.2229079008102417 + 1 + <_> + + + + <_>11 2 2 6 -1. + <_>12 2 1 3 2. + <_>11 5 1 3 2. + 0 + 1.5057219570735469e-005 + 0.4107285141944885 + 0.5747591257095337 + <_> + + <_> + + + + <_>7 17 3 3 -1. + <_>8 17 1 3 3. + 0 + -5.4136710241436958e-003 + 0.2065797001123428 + 1 + <_> + + + + <_>8 15 4 3 -1. + <_>8 16 4 1 3. + 0 + 5.3679239936172962e-003 + 0.4926423132419586 + 0.7139484882354736 + <_> + + <_> + + + + <_>10 15 4 2 -1. + <_>12 15 2 1 2. + <_>10 16 2 1 2. + 0 + -3.1426660716533661e-003 + 0.6780086755752564 + 1 + <_> + + + + <_>13 13 4 3 -1. + <_>13 14 4 1 3. + 0 + 0.0109073901548982 + 0.5214930176734924 + 0.1143995970487595 + <_> + + <_> + + + + <_>3 13 4 3 -1. + <_>3 14 4 1 3. + 0 + 5.8436761610209942e-003 + 1 + 0.1937526017427445 + <_> + + + + <_>7 2 2 6 -1. + <_>7 2 1 3 2. + <_>8 5 1 3 2. + 0 + 9.0507230197545141e-005 + 0.3812577128410339 + 0.5514187812805176 + <_> + + <_> + + + + <_>2 1 16 3 -1. + <_>2 2 16 1 3. + 0 + -0.0163457896560431 + 0.2474023997783661 + 1 + <_> + + + + <_>10 15 4 2 -1. + <_>12 15 2 1 2. + <_>10 16 2 1 2. + 0 + 1.5987500082701445e-003 + 0.4817782938480377 + 0.5923079848289490 + <_> + + <_> + + + + <_>6 15 4 2 -1. + <_>6 15 2 1 2. + <_>8 16 2 1 2. + 0 + -4.0257978253066540e-003 + 0.7508208751678467 + 1 + <_> + + + + <_>3 0 13 3 -1. + <_>3 1 13 1 3. + 0 + -6.7750471644103527e-003 + 0.2879810929298401 + 0.5199695229530335 + <_> + + <_> + + + + <_>0 9 20 3 -1. + <_>0 10 20 1 3. + 0 + -3.2470689620822668e-003 + 0.3044910132884979 + 1 + <_> + + + + <_>6 7 9 2 -1. + <_>6 8 9 1 2. + 0 + 1.5409620245918632e-003 + 0.4063482880592346 + 0.5676562786102295 + <_> + + <_> + + + + <_>8 14 3 6 -1. + <_>9 14 1 6 3. + 0 + -0.0128581197932363 + 0.0967175588011742 + 1 + <_> + + + + <_>9 10 2 2 -1. + <_>9 11 2 1 2. + 0 + -1.4824670506641269e-004 + 0.4537833034992218 + 0.6115375161170960 + <_> + + <_> + + + + <_>9 7 2 5 -1. + <_>9 7 1 5 2. + 0 + -9.0210810303688049e-003 + 1 + 0.4807750880718231 + <_> + + + + <_>5 6 10 3 -1. + <_>5 6 5 3 2. + 0 + -0.0287950299680233 + 0.3403795063495636 + 0.5255529284477234 + <_> + + <_> + + + + <_>9 7 2 5 -1. + <_>10 7 1 5 2. + 0 + 9.0210810303688049e-003 + 1 + 0.7505835890769959 + <_> + + + + <_>5 6 10 3 -1. + <_>10 6 5 3 2. + 0 + 7.4121179059147835e-003 + 0.5455446839332581 + 0.3226068913936615 + <_> + + <_> + + + + <_>13 9 2 2 -1. + <_>13 9 1 2 2. + 0 + -3.7217529024928808e-003 + 0.2311848998069763 + 1 + <_> + + + + <_>4 3 12 11 -1. + <_>8 3 4 11 3. + 0 + 0.1986588984727860 + 0.5271047949790955 + 0.1469929963350296 + <_> + + <_> + + + + <_>7 1 2 7 -1. + <_>8 1 1 7 2. + 0 + 1.5208719560177997e-005 + 0.3678138852119446 + 1 + <_> + + + + <_>7 4 3 8 -1. + <_>8 4 1 8 3. + 0 + -3.9089918136596680e-003 + 0.7131929993629456 + 0.4993866980075836 + <_> + + <_> + + + + <_>13 9 2 2 -1. + <_>13 9 1 2 2. + 0 + 2.5106288958340883e-003 + 0.5312054157257080 + 1 + <_> + + + + <_>11 6 2 2 -1. + <_>12 6 1 1 2. + <_>11 7 1 1 2. + 0 + 2.3921660613268614e-004 + 0.4689378142356873 + 0.5714021921157837 + <_> + + <_> + + + + <_>5 4 2 3 -1. + <_>5 5 2 1 3. + 0 + 6.9443131797015667e-003 + 1 + 0.6948797702789307 + <_> + + + + <_>6 5 1 3 -1. + <_>6 6 1 1 3. + 0 + 1.2065629707649350e-003 + 0.4004504978656769 + 0.5874881744384766 + <_> + + <_> + + + + <_>13 9 2 2 -1. + <_>13 9 1 2 2. + 0 + 2.5106288958340883e-003 + 0.5329571962356567 + 1 + <_> + + + + <_>16 14 3 3 -1. + <_>16 15 3 1 3. + 0 + 1.7514040227979422e-003 + 0.5545849204063416 + 0.3449581861495972 + <_> + + <_> + + + + <_>5 9 2 2 -1. + <_>6 9 1 2 2. + 0 + -4.1978210210800171e-003 + 0.1217183023691177 + 1 + <_> + + + + <_>1 14 3 3 -1. + <_>1 15 3 1 3. + 0 + 1.3092850567772985e-003 + 0.5375049710273743 + 0.3415625095367432 + <_> + + <_> + + + + <_>13 1 1 6 -1. + <_>13 3 1 2 3. + 0 + 6.7396182566881180e-004 + 0.4195179045200348 + 1 + <_> + + + + <_>13 3 7 2 -1. + <_>13 4 7 1 2. + 0 + -0.0105307102203369 + 0.3460753858089447 + 0.5155860185623169 + <_> + + <_> + + + + <_>0 6 20 14 -1. + <_>0 13 20 7 2. + 0 + -0.4067229926586151 + 0.0580656789243221 + 1 + <_> + + + + <_>0 4 3 6 -1. + <_>0 6 3 2 3. + 0 + -0.0263145491480827 + 0.1473449021577835 + 0.5559378266334534 + <_> + + <_> + + + + <_>10 1 9 6 -1. + <_>10 3 9 2 3. + 0 + 2.2557149641215801e-003 + 1 + 0.5477715134620667 + <_> + + + + <_>8 0 12 5 -1. + <_>8 0 6 5 2. + 0 + 0.0121548604220152 + 0.4207791090011597 + 0.5621880888938904 + <_> + + <_> + + + + <_>0 0 18 5 -1. + <_>6 0 6 5 3. + 0 + -0.0184365399181843 + 0.6447147130966187 + 1 + <_> + + + + <_>1 1 9 6 -1. + <_>1 3 9 2 3. + 0 + 5.3676147945225239e-004 + 0.2765127122402191 + 0.4888595938682556 + <_> + + <_> + + + + <_>15 15 2 2 -1. + <_>15 16 2 1 2. + 0 + -2.6265541091561317e-003 + 1 + 0.5264691114425659 + <_> + + + + <_>13 16 3 4 -1. + <_>13 18 3 2 2. + 0 + -5.1119807176291943e-004 + 0.5785310268402100 + 0.4291102886199951 + <_> + + <_> + + + + <_>3 15 2 2 -1. + <_>3 16 2 1 2. + 0 + 4.1454841266386211e-004 + 1 + 0.3455410897731781 + <_> + + + + <_>4 16 3 4 -1. + <_>4 18 3 2 2. + 0 + -5.5028748465701938e-004 + 0.6026918888092041 + 0.4143893122673035 + <_> + + <_> + + + + <_>11 14 1 3 -1. + <_>11 15 1 1 3. + 0 + -1.0347720235586166e-003 + 0.6095293760299683 + 1 + <_> + + + + <_>9 13 5 3 -1. + <_>9 14 5 1 3. + 0 + -3.3966631162911654e-003 + 0.6108282208442688 + 0.4707720875740051 + <_> + + <_> + + + + <_>0 0 3 6 -1. + <_>0 2 3 2 3. + 0 + 3.1795909162610769e-003 + 1 + 0.3244366943836212 + <_> + + + + <_>4 1 6 3 -1. + <_>6 1 2 3 3. + 0 + -1.6528950072824955e-004 + 0.3830757141113281 + 0.5734326243400574 + <_> + + <_> + + + + <_>9 13 4 3 -1. + <_>9 14 4 1 3. + 0 + 8.3725210279226303e-003 + 1 + 0.6610919237136841 + <_> + + + + <_>8 15 5 3 -1. + <_>8 16 5 1 3. + 0 + -2.5799809955060482e-003 + 0.6139307022094727 + 0.4686149954795837 + <_> + + <_> + + + + <_>8 3 3 2 -1. + <_>9 3 1 2 3. + 0 + 9.0194388758391142e-004 + 1 + 0.3520022034645081 + <_> + + + + <_>1 8 18 2 -1. + <_>1 9 18 1 2. + 0 + 3.6952210939489305e-004 + 0.2578754127025604 + 0.5467242002487183 + <_> + + <_> + + + + <_>11 14 1 3 -1. + <_>11 15 1 1 3. + 0 + 9.9746137857437134e-004 + 0.4820146858692169 + 1 + <_> + + + + <_>8 13 6 3 -1. + <_>8 14 6 1 3. + 0 + -3.6688039544969797e-003 + 0.5710150003433228 + 0.4831911027431488 + <_> + + <_> + + + + <_>8 14 1 3 -1. + <_>8 15 1 1 3. + 0 + -8.9501030743122101e-004 + 0.6133679151535034 + 1 + <_> + + + + <_>4 13 12 4 -1. + <_>4 13 6 2 2. + <_>10 15 6 2 2. + 0 + 5.1904921419918537e-003 + 0.4928582906723023 + 0.2581309080123901 + <_> + + <_> + + + + <_>10 7 2 2 -1. + <_>10 7 1 2 2. + 0 + 4.2274440056644380e-004 + 0.4471124112606049 + 1 + <_> + + + + <_>13 4 2 8 -1. + <_>14 4 1 4 2. + <_>13 8 1 4 2. + 0 + 8.5176713764667511e-003 + 0.5161024928092957 + 0.3316533863544464 + <_> + + <_> + + + + <_>0 5 4 6 -1. + <_>0 7 4 2 3. + 0 + -0.0366236083209515 + 0.0926062166690826 + 1 + <_> + + + + <_>8 7 2 2 -1. + <_>9 7 1 2 2. + 0 + -4.1103712283074856e-003 + 0.8522114753723145 + 0.5137907862663269 + <_> + + <_> + + + + <_>13 0 3 7 -1. + <_>14 0 1 7 3. + 0 + -6.6017331555485725e-003 + 1 + 0.5459060072898865 + <_> + + + + <_>11 2 2 14 -1. + <_>11 2 1 14 2. + 0 + 0.0255786404013634 + 0.5219352841377258 + 0.1927185952663422 + <_> + + <_> + + + + <_>4 0 3 7 -1. + <_>5 0 1 7 3. + 0 + 0.0114474399015307 + 1 + 0.1916002035140991 + <_> + + + + <_>5 5 8 12 -1. + <_>5 5 4 6 2. + <_>9 11 4 6 2. + 0 + 7.2427501436322927e-004 + 0.5231571197509766 + 0.3535340130329132 + <_> + + <_> + + + + <_>11 4 6 3 -1. + <_>11 5 6 1 3. + 0 + 9.7127500921487808e-003 + 1 + 0.6464101076126099 + <_> + + + + <_>12 3 4 3 -1. + <_>12 4 4 1 3. + 0 + -0.0113375699147582 + 0.7383037805557251 + 0.4964743852615356 + <_> + + <_> + + + + <_>5 5 10 12 -1. + <_>5 5 5 6 2. + <_>10 11 5 6 2. + 0 + -8.1453882157802582e-003 + 0.3611705899238586 + 1 + <_> + + + + <_>3 6 12 3 -1. + <_>9 6 6 3 2. + 0 + -8.5570756345987320e-003 + 0.3421907126903534 + 0.5943511724472046 + <_> + + <_> + + + + <_>9 6 2 7 -1. + <_>9 6 1 7 2. + 0 + 2.2993308957666159e-003 + 0.4550104141235352 + 1 + <_> + + + + <_>9 5 2 4 -1. + <_>9 5 1 4 2. + 0 + 3.8430930580943823e-003 + 0.4716862142086029 + 0.6656190752983093 + <_> + + <_> + + + + <_>8 7 3 3 -1. + <_>9 7 1 3 3. + 0 + -9.9116540513932705e-004 + 1 + 0.4592716991901398 + <_> + + + + <_>5 1 6 4 -1. + <_>7 1 2 4 3. + 0 + 0.0254964698106050 + 0.6563401222229004 + 0.1258835047483444 + <_> + + <_> + + + + <_>13 16 7 3 -1. + <_>13 17 7 1 3. + 0 + -0.0157483592629433 + 1 + 0.5239502191543579 + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + -0.0180461201816797 + 0.8015851974487305 + 0.5007957816123962 + <_> + + <_> + + + + <_>0 16 7 3 -1. + <_>0 17 7 1 3. + 0 + 0.0103233903646469 + 1 + 0.2274820059537888 + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + 1.6452240524813533e-003 + 0.4351946115493774 + 0.5867627859115601 + <_> + + <_> + + + + <_>12 9 8 10 -1. + <_>12 9 4 10 2. + 0 + 0.0158811490982771 + 0.4465051889419556 + 1 + <_> + + + + <_>8 10 12 5 -1. + <_>12 10 4 5 3. + 0 + 0.0105865197256207 + 0.4544458091259003 + 0.5707110762596130 + <_> + + <_> + + + + <_>0 9 8 10 -1. + <_>4 9 4 10 2. + 0 + -0.0215316899120808 + 0.6527643799781799 + 1 + <_> + + + + <_>0 10 12 5 -1. + <_>4 10 4 5 3. + 0 + 5.2480469457805157e-003 + 0.3444727957248688 + 0.5324636101722717 + 25.6093006134033200 + 9 + -1 + <_> + + + <_> + + <_> + + + + <_>2 3 6 2 -1. + <_>5 3 3 2 2. + 0 + 1.8219340126961470e-003 + 0.3108788132667542 + 1 + <_> + + + + <_>0 0 17 9 -1. + <_>0 3 17 3 3. + 0 + 8.1313941627740860e-003 + 0.3133237063884735 + 0.6645867228507996 + <_> + + <_> + + + + <_>4 7 12 2 -1. + <_>8 7 4 2 3. + 0 + 1.7055979697033763e-003 + 0.2640131115913391 + 1 + <_> + + + + <_>10 4 6 4 -1. + <_>12 4 2 4 3. + 0 + -7.4483548814896494e-005 + 0.5647205114364624 + 0.3485372960567474 + <_> + + <_> + + + + <_>0 10 20 4 -1. + <_>0 12 20 2 2. + 0 + 3.8342390325851738e-004 + 1 + 0.3140654861927033 + <_> + + + + <_>4 3 6 5 -1. + <_>6 3 2 5 3. + 0 + 3.1868910882622004e-003 + 0.6489198803901672 + 0.3887729048728943 + <_> + + <_> + + + + <_>1 1 18 4 -1. + <_>7 1 6 4 3. + 0 + 0.1604432016611099 + 1 + 0.7216529846191406 + <_> + + + + <_>13 9 2 3 -1. + <_>13 9 1 3 2. + 0 + -6.7285560071468353e-003 + 0.1653137952089310 + 0.5139825940132141 + <_> + + <_> + + + + <_>6 15 7 4 -1. + <_>6 17 7 2 2. + 0 + 7.2638481469766703e-006 + 0.3140619993209839 + 1 + <_> + + + + <_>3 17 4 2 -1. + <_>3 18 4 1 2. + 0 + 5.5551197146996856e-004 + 0.5993698835372925 + 0.3317398130893707 + <_> + + <_> + + + + <_>9 4 8 10 -1. + <_>9 9 8 5 2. + 0 + -0.0108223203569651 + 0.2652938067913055 + 1 + <_> + + + + <_>9 17 3 2 -1. + <_>10 17 1 2 3. + 0 + -4.5834020711481571e-003 + 0.1849568933248520 + 0.5313957929611206 + <_> + + <_> + + + + <_>8 2 4 8 -1. + <_>8 6 4 4 2. + 0 + -3.0205070506781340e-003 + 1 + 0.4040099978446960 + <_> + + + + <_>3 4 14 12 -1. + <_>3 4 7 6 2. + <_>10 10 7 6 2. + 0 + 0.0778646171092987 + 0.6158189773559570 + 0.1786486953496933 + <_> + + <_> + + + + <_>7 7 6 4 -1. + <_>9 7 2 4 3. + 0 + 0.0264943800866604 + 0.4511089920997620 + 1 + <_> + + + + <_>6 7 9 4 -1. + <_>6 9 9 2 2. + 0 + 0.0369121097028255 + 0.4528219997882843 + 0.5972282886505127 + <_> + + <_> + + + + <_>2 10 3 3 -1. + <_>2 11 3 1 3. + 0 + 5.7857790961861610e-003 + 1 + 0.2533892095088959 + <_> + + + + <_>4 6 2 9 -1. + <_>4 9 2 3 3. + 0 + 9.3849771656095982e-004 + 0.3410412073135376 + 0.5923643708229065 + <_> + + <_> + + + + <_>9 11 3 3 -1. + <_>9 12 3 1 3. + 0 + -0.0110031999647617 + 0.6958044171333313 + 1 + <_> + + + + <_>3 1 15 2 -1. + <_>3 2 15 1 2. + 0 + -1.1737640015780926e-003 + 0.3851084113121033 + 0.5408189296722412 + <_> + + <_> + + + + <_>9 8 2 3 -1. + <_>9 9 2 1 3. + 0 + -3.6596669815480709e-003 + 0.2009308934211731 + 1 + <_> + + + + <_>9 6 2 5 -1. + <_>10 6 1 5 2. + 0 + -2.4822750128805637e-003 + 0.6295393109321594 + 0.4395040869712830 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 8 2 1 3. + 0 + -4.4606071896851063e-003 + 0.2405299991369247 + 1 + <_> + + + + <_>4 10 12 10 -1. + <_>4 15 12 5 2. + 0 + -3.5969649907201529e-003 + 0.5450174212455750 + 0.3782357871532440 + <_> + + <_> + + + + <_>0 10 4 2 -1. + <_>0 11 4 1 2. + 0 + -3.6222559865564108e-003 + 0.3033896982669830 + 1 + <_> + + + + <_>5 15 9 2 -1. + <_>5 16 9 1 2. + 0 + 1.2059339787811041e-003 + 0.4633778929710388 + 0.6335952281951904 + <_> + + <_> + + + + <_>8 14 6 3 -1. + <_>8 15 6 1 3. + 0 + 4.3124938383698463e-003 + 1 + 0.6598826050758362 + <_> + + + + <_>8 16 4 3 -1. + <_>8 17 4 1 3. + 0 + -4.4961250387132168e-003 + 0.6621696949005127 + 0.4755246937274933 + <_> + + <_> + + + + <_>8 9 4 2 -1. + <_>8 10 4 1 2. + 0 + -1.3860689941793680e-003 + 0.2801201045513153 + 1 + <_> + + + + <_>3 3 14 2 -1. + <_>3 4 14 1 2. + 0 + -5.1588460337370634e-004 + 0.3829489052295685 + 0.5623626708984375 + <_> + + <_> + + + + <_>11 12 1 2 -1. + <_>11 13 1 1 2. + 0 + 7.0330002927221358e-005 + 0.4536342918872833 + 1 + <_> + + + + <_>4 12 12 1 -1. + <_>8 12 4 1 3. + 0 + -2.0976549421902746e-004 + 0.5608139038085938 + 0.4265779852867127 + <_> + + <_> + + + + <_>0 2 1 2 -1. + <_>0 3 1 1 2. + 0 + 1.3642259873449802e-003 + 1 + 0.2637091875076294 + <_> + + + + <_>7 4 4 6 -1. + <_>9 4 2 6 2. + 0 + 1.5483660390600562e-003 + 0.4170750975608826 + 0.5932987928390503 + <_> + + <_> + + + + <_>0 2 20 14 -1. + <_>10 2 10 7 2. + <_>0 9 10 7 2. + 0 + 0.1917960941791534 + 0.5256764292716980 + 1 + <_> + + + + <_>14 6 1 3 -1. + <_>14 7 1 1 3. + 0 + -4.4776909053325653e-003 + 0.6632621884346008 + 0.4892588853836060 + <_> + + <_> + + + + <_>0 4 20 12 -1. + <_>0 4 10 6 2. + <_>10 10 10 6 2. + 0 + -0.1264917999505997 + 0.1499778926372528 + 1 + <_> + + + + <_>8 12 1 2 -1. + <_>8 13 1 1 2. + 0 + 6.5253327193204314e-005 + 0.4233320057392120 + 0.5756040215492249 + <_> + + <_> + + + + <_>9 18 3 2 -1. + <_>10 18 1 2 3. + 0 + 4.1856421157717705e-003 + 0.5288826823234558 + 1 + <_> + + + + <_>9 17 6 2 -1. + <_>11 17 2 2 3. + 0 + 2.7478230185806751e-004 + 0.4524017870426178 + 0.5604125261306763 + <_> + + <_> + + + + <_>5 6 2 3 -1. + <_>5 7 2 1 3. + 0 + -2.2906810045242310e-003 + 0.5578274130821228 + 1 + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + 1.6744500026106834e-003 + 0.3323057889938355 + 0.5558788180351257 + <_> + + <_> + + + + <_>14 15 3 2 -1. + <_>14 16 3 1 2. + 0 + 1.2349759927019477e-003 + 1 + 0.3653947114944458 + <_> + + + + <_>11 3 3 4 -1. + <_>12 3 1 4 3. + 0 + -8.7158754467964172e-003 + 0.1924533993005753 + 0.5313649773597717 + <_> + + <_> + + + + <_>3 15 3 2 -1. + <_>3 16 3 1 2. + 0 + 4.6613621525466442e-003 + 1 + 0.2027730941772461 + <_> + + + + <_>9 12 2 3 -1. + <_>9 13 2 1 3. + 0 + -8.5815992206335068e-003 + 0.7636060118675232 + 0.5140826106071472 + <_> + + <_> + + + + <_>9 13 3 7 -1. + <_>10 13 1 7 3. + 0 + 0.0143521204590797 + 0.5252975821495056 + 1 + <_> + + + + <_>12 12 5 3 -1. + <_>12 13 5 1 3. + 0 + -7.7948719263076782e-003 + 0.2632937133312225 + 0.5328689217567444 + <_> + + <_> + + + + <_>8 18 3 2 -1. + <_>9 18 1 2 3. + 0 + -3.4155680332332850e-003 + 0.2416087985038757 + 1 + <_> + + + + <_>4 7 12 4 -1. + <_>4 7 6 2 2. + <_>10 9 6 2 2. + 0 + -4.2639090679585934e-003 + 0.3936544954776764 + 0.5478742122650147 + <_> + + <_> + + + + <_>6 19 14 1 -1. + <_>6 19 7 1 2. + 0 + 8.7177697569131851e-003 + 0.4788199067115784 + 1 + <_> + + + + <_>16 14 3 2 -1. + <_>16 15 3 1 2. + 0 + -3.2232629600912333e-003 + 0.3631612062454224 + 0.5288316011428833 + <_> + + <_> + + + + <_>1 0 6 10 -1. + <_>1 0 3 5 2. + <_>4 5 3 5 2. + 0 + -0.0421883687376976 + 0.6931139230728149 + 1 + <_> + + + + <_>1 0 4 10 -1. + <_>1 0 2 5 2. + <_>3 5 2 5 2. + 0 + 0.0198757499456406 + 0.4520100057125092 + 0.6855055093765259 + <_> + + <_> + + + + <_>15 3 5 6 -1. + <_>15 5 5 2 3. + 0 + -0.0311345104128122 + 1 + 0.5300424098968506 + <_> + + + + <_>9 5 2 15 -1. + <_>9 10 2 5 3. + 0 + 5.7032387703657150e-003 + 0.5606892108917236 + 0.4230622947216034 + <_> + + <_> + + + + <_>0 3 5 6 -1. + <_>0 5 5 2 3. + 0 + 5.2733682096004486e-003 + 1 + 0.3247228860855103 + <_> + + + + <_>6 0 3 2 -1. + <_>7 0 1 2 3. + 0 + -3.1231069006025791e-003 + 0.1985695958137512 + 0.5349872708320618 + <_> + + <_> + + + + <_>12 8 8 2 -1. + <_>16 8 4 1 2. + <_>12 9 4 1 2. + 0 + 4.6453849063254893e-004 + 0.4207508862018585 + 1 + <_> + + + + <_>5 8 12 1 -1. + <_>9 8 4 1 3. + 0 + 0.0303558893501759 + 0.5153458714485169 + 0.3118101060390472 + <_> + + <_> + + + + <_>3 13 3 3 -1. + <_>3 14 3 1 3. + 0 + -4.2992769740521908e-003 + 0.3274506926536560 + 1 + <_> + + + + <_>5 13 3 2 -1. + <_>5 14 3 1 2. + 0 + 1.9509199773892760e-004 + 0.5953078269958496 + 0.4225521087646484 + <_> + + <_> + + + + <_>9 15 3 3 -1. + <_>9 16 3 1 3. + 0 + -7.7784480527043343e-003 + 0.7211179733276367 + 1 + <_> + + + + <_>7 15 7 3 -1. + <_>7 16 7 1 3. + 0 + 0.0169175993651152 + 0.4936591982841492 + 0.7030277252197266 + <_> + + <_> + + + + <_>3 14 11 6 -1. + <_>3 16 11 2 3. + 0 + -0.0519485697150230 + 0.1425534933805466 + 1 + <_> + + + + <_>0 19 14 1 -1. + <_>7 19 7 1 2. + 0 + -5.4751220159232616e-003 + 0.6059331893920898 + 0.4393995106220245 + <_> + + <_> + + + + <_>9 17 6 2 -1. + <_>11 17 2 2 3. + 0 + 1.5210839592327829e-005 + 0.4488849937915802 + 1 + <_> + + + + <_>12 11 6 2 -1. + <_>14 11 2 2 3. + 0 + 1.0235579684376717e-003 + 0.4256550073623657 + 0.5795438289642334 + <_> + + <_> + + + + <_>5 17 6 2 -1. + <_>7 17 2 2 3. + 0 + -1.0427719826111570e-004 + 0.4246039986610413 + 1 + <_> + + + + <_>0 1 9 10 -1. + <_>3 1 3 10 3. + 0 + 8.7853781878948212e-003 + 0.4958009123802185 + 0.6759430766105652 + <_> + + <_> + + + + <_>10 1 3 3 -1. + <_>11 1 1 3 3. + 0 + 3.4012699034065008e-003 + 0.5423480868339539 + 1 + <_> + + + + <_>9 5 6 4 -1. + <_>9 5 3 4 2. + 0 + 5.8582378551363945e-004 + 0.3636542856693268 + 0.5464348793029785 + <_> + + <_> + + + + <_>7 1 3 3 -1. + <_>8 1 1 3 3. + 0 + -2.2973360028117895e-003 + 0.2548818886280060 + 1 + <_> + + + + <_>0 4 4 11 -1. + <_>2 4 2 11 2. + 0 + -0.0143301896750927 + 0.6587656736373901 + 0.4532802104949951 + <_> + + <_> + + + + <_>9 5 6 4 -1. + <_>9 5 3 4 2. + 0 + 9.8565965890884399e-004 + 0.3822771012783051 + 1 + <_> + + + + <_>6 0 8 10 -1. + <_>10 0 4 5 2. + <_>6 5 4 5 2. + 0 + -0.0466407611966133 + 0.3077321946620941 + 0.5244132876396179 + <_> + + <_> + + + + <_>6 6 5 14 -1. + <_>6 13 5 7 2. + 0 + -0.1190730035305023 + 0.1033862978219986 + 1 + <_> + + + + <_>8 5 4 14 -1. + <_>8 12 4 7 2. + 0 + 0.0193332806229591 + 0.5554745197296143 + 0.3221316933631897 + <_> + + <_> + + + + <_>7 7 6 5 -1. + <_>9 7 2 5 3. + 0 + 0.0314278490841389 + 0.4682379066944122 + 1 + <_> + + + + <_>9 3 3 9 -1. + <_>9 6 3 3 3. + 0 + 2.0082130504306406e-004 + 0.5373070240020752 + 0.3800666928291321 + <_> + + <_> + + + + <_>8 1 3 3 -1. + <_>9 1 1 3 3. + 0 + -6.2584900297224522e-003 + 0.1799207031726837 + 1 + <_> + + + + <_>9 6 2 4 -1. + <_>10 6 1 4 2. + 0 + 8.2861045375466347e-003 + 0.5095068812370300 + 0.7544605135917664 + <_> + + <_> + + + + <_>10 8 6 9 -1. + <_>10 8 3 9 2. + 0 + 2.0529709290713072e-003 + 0.5628644824028015 + 1 + <_> + + + + <_>16 4 3 8 -1. + <_>17 4 1 8 3. + 0 + 3.2524869311600924e-003 + 0.4801689088344574 + 0.5802102088928223 + <_> + + <_> + + + + <_>5 9 10 6 -1. + <_>5 9 5 3 2. + <_>10 12 5 3 2. + 0 + -0.0318849012255669 + 0.1742745041847229 + 1 + <_> + + + + <_>5 5 6 4 -1. + <_>8 5 3 4 2. + 0 + 1.8379340181127191e-003 + 0.3466596901416779 + 0.5107154846191406 + <_> + + <_> + + + + <_>9 8 4 2 -1. + <_>9 9 4 1 2. + 0 + -4.8512680223211646e-004 + 1 + 0.5326086282730103 + <_> + + + + <_>11 7 2 2 -1. + <_>11 7 1 2 2. + 0 + -2.5407879147678614e-003 + 0.6342775225639343 + 0.4992693066596985 + <_> + + <_> + + + + <_>8 12 4 8 -1. + <_>8 12 2 4 2. + <_>10 16 2 4 2. + 0 + -5.1559060811996460e-003 + 0.3433429002761841 + 1 + <_> + + + + <_>0 1 4 9 -1. + <_>0 4 4 3 3. + 0 + -0.0449687503278255 + 0.1868136972188950 + 0.5215464830398560 + <_> + + <_> + + + + <_>9 10 3 3 -1. + <_>9 11 3 1 3. + 0 + 5.8984281495213509e-003 + 1 + 0.6229305267333984 + <_> + + + + <_>8 11 4 2 -1. + <_>8 12 4 1 2. + 0 + 3.2763120252639055e-003 + 0.4935772120952606 + 0.7217944860458374 + <_> + + <_> + + + + <_>7 8 4 2 -1. + <_>7 9 4 1 2. + 0 + -1.0161520185647532e-004 + 1 + 0.5007976293563843 + <_> + + + + <_>7 8 6 1 -1. + <_>9 8 2 1 3. + 0 + -1.6290300118271261e-004 + 0.6024149060249329 + 0.2329508066177368 + <_> + + <_> + + + + <_>16 0 4 9 -1. + <_>16 0 2 9 2. + 0 + 9.0541364625096321e-003 + 0.4510416984558106 + 1 + <_> + + + + <_>16 0 3 6 -1. + <_>16 3 3 3 2. + 0 + 0.0353984907269478 + 0.5141996741294861 + 0.2860291898250580 + <_> + + <_> + + + + <_>0 0 4 9 -1. + <_>2 0 2 9 2. + 0 + 5.6469351984560490e-003 + 0.4704925119876862 + 1 + <_> + + + + <_>1 0 3 6 -1. + <_>1 3 3 3 2. + 0 + -2.4807190056890249e-003 + 0.4179851114749908 + 0.6726647019386292 + <_> + + <_> + + + + <_>9 7 6 9 -1. + <_>11 7 2 9 3. + 0 + -4.1088787838816643e-003 + 0.5809801816940308 + 1 + <_> + + + + <_>10 6 3 6 -1. + <_>11 6 1 6 3. + 0 + -2.0714469719678164e-003 + 0.6074783802032471 + 0.4524059891700745 + <_> + + <_> + + + + <_>1 2 18 2 -1. + <_>1 2 9 1 2. + <_>10 3 9 1 2. + 0 + -2.8939060866832733e-003 + 0.3383519947528839 + 1 + <_> + + + + <_>5 8 6 8 -1. + <_>7 8 2 8 3. + 0 + 1.3467279495671391e-003 + 0.5696910023689270 + 0.3970845043659210 + <_> + + <_> + + + + <_>9 0 6 16 -1. + <_>11 0 2 16 3. + 0 + -0.0907791331410408 + 0.1502701938152313 + 1 + <_> + + + + <_>14 1 6 18 -1. + <_>17 1 3 9 2. + <_>14 10 3 9 2. + 0 + -0.0831717625260353 + 0.7573670744895935 + 0.4936437010765076 + <_> + + <_> + + + + <_>2 9 2 3 -1. + <_>2 10 2 1 3. + 0 + -1.4107000315561891e-003 + 0.3390932977199554 + 1 + <_> + + + + <_>0 1 6 18 -1. + <_>0 1 3 9 2. + <_>3 10 3 9 2. + 0 + 0.0556687600910664 + 0.5025097131729126 + 0.7422083020210266 + <_> + + <_> + + + + <_>11 8 4 12 -1. + <_>11 8 2 12 2. + 0 + 0.0577015392482281 + 0.5197371840476990 + 1 + <_> + + + + <_>2 1 18 18 -1. + <_>2 10 18 9 2. + 0 + -0.4250329136848450 + 0.0973469167947769 + 0.5185739994049072 + <_> + + <_> + + + + <_>6 3 3 1 -1. + <_>7 3 1 1 3. + 0 + -4.4380719191394746e-004 + 0.3649350106716156 + 1 + <_> + + + + <_>4 12 2 2 -1. + <_>4 13 2 1 2. + 0 + 1.7924769781529903e-004 + 0.5619279146194458 + 0.3760297000408173 + <_> + + <_> + + + + <_>8 13 5 3 -1. + <_>8 14 5 1 3. + 0 + 5.0382469780743122e-003 + 1 + 0.6328445076942444 + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + 0.0151911703869700 + 0.4936082065105438 + 0.7426524758338928 + <_> + + <_> + + + + <_>3 12 5 3 -1. + <_>3 13 5 1 3. + 0 + -0.0123003898188472 + 0.1389349997043610 + 1 + <_> + + + + <_>6 3 3 4 -1. + <_>7 3 1 4 3. + 0 + 1.5168030513450503e-003 + 0.5091962218284607 + 0.3482648134231567 + <_> + + <_> + + + + <_>11 10 2 2 -1. + <_>12 10 1 1 2. + <_>11 11 1 1 2. + 0 + 9.5754547510296106e-004 + 1 + 0.6036316752433777 + <_> + + + + <_>5 8 12 1 -1. + <_>9 8 4 1 3. + 0 + -0.0189622007310390 + 0.2319173067808151 + 0.5116652846336365 + <_> + + <_> + + + + <_>8 4 4 8 -1. + <_>10 4 2 8 2. + 0 + -0.0222722608596087 + 0.6555022001266480 + 1 + <_> + + + + <_>6 6 8 5 -1. + <_>10 6 4 5 2. + 0 + -0.0251452308148146 + 0.1326071023941040 + 0.4674034118652344 + <_> + + <_> + + + + <_>10 4 6 4 -1. + <_>12 4 2 4 3. + 0 + 0.0195339005440474 + 0.5182027220726013 + 1 + <_> + + + + <_>12 7 2 2 -1. + <_>13 7 1 1 2. + <_>12 8 1 1 2. + 0 + -1.1231349781155586e-003 + 0.6318243145942688 + 0.4825519025325775 + <_> + + <_> + + + + <_>3 5 10 8 -1. + <_>3 9 10 4 2. + 0 + -1.4861139934509993e-003 + 0.2918671071529388 + 1 + <_> + + + + <_>7 1 2 12 -1. + <_>7 7 2 6 2. + 0 + 3.5002888762392104e-004 + 0.5621371269226074 + 0.4249213039875031 + <_> + + <_> + + + + <_>12 7 2 2 -1. + <_>13 7 1 1 2. + <_>12 8 1 1 2. + 0 + -1.1231349781155586e-003 + 1 + 0.4813745021820068 + <_> + + + + <_>11 13 1 6 -1. + <_>11 16 1 3 2. + 0 + 0.0104097397997975 + 0.5184006094932556 + 0.2051223069429398 + <_> + + <_> + + + + <_>5 1 6 15 -1. + <_>7 1 2 15 3. + 0 + -0.0878325626254082 + 0.1179921999573708 + 1 + <_> + + + + <_>6 7 2 2 -1. + <_>6 7 1 1 2. + <_>7 8 1 1 2. + 0 + 1.6584879485890269e-003 + 0.4987811148166657 + 0.6973755955696106 + <_> + + <_> + + + + <_>17 5 2 2 -1. + <_>17 6 2 1 2. + 0 + -2.3008750285953283e-003 + 1 + 0.5339831113815308 + <_> + + + + <_>10 3 4 10 -1. + <_>12 3 2 5 2. + <_>10 8 2 5 2. + 0 + 0.0330261699855328 + 0.5033289194107056 + 0.6851906776428223 + <_> + + <_> + + + + <_>1 5 2 2 -1. + <_>1 6 2 1 2. + 0 + -1.3585069682449102e-003 + 0.3002822101116180 + 1 + <_> + + + + <_>7 10 2 2 -1. + <_>7 10 1 1 2. + <_>8 11 1 1 2. + 0 + 7.8067491995170712e-004 + 0.4593083858489990 + 0.6440045237541199 + <_> + + <_> + + + + <_>3 12 14 4 -1. + <_>10 12 7 2 2. + <_>3 14 7 2 2. + 0 + -0.0180257596075535 + 1 + 0.5311291217803955 + <_> + + + + <_>9 15 3 2 -1. + <_>9 16 3 1 2. + 0 + 1.2354910140857100e-003 + 0.4729106128215790 + 0.5721461176872253 + <_> + + <_> + + + + <_>1 13 3 3 -1. + <_>1 14 3 1 3. + 0 + -9.2583027435466647e-004 + 0.3662332892417908 + 1 + <_> + + + + <_>0 3 1 2 -1. + <_>0 4 1 1 2. + 0 + 8.0123997759073973e-004 + 0.5361989736557007 + 0.3008632957935333 + 32.6471290588378910 + 10 + -1 + <_> + + + <_> + + <_> + + + + <_>7 7 6 1 -1. + <_>9 7 2 1 3. + 0 + 2.4914839304983616e-003 + 0.3422389030456543 + 1 + <_> + + + + <_>0 4 16 6 -1. + <_>0 6 16 2 3. + 0 + -0.0504885986447334 + 0.7703458070755005 + 0.4516390860080719 + <_> + + <_> + + + + <_>9 3 2 14 -1. + <_>9 10 2 7 2. + 0 + -7.7838351717218757e-004 + 1 + 0.3256342113018036 + <_> + + + + <_>12 0 4 3 -1. + <_>12 0 2 3 2. + 0 + 2.3572890495415777e-004 + 0.3406555950641632 + 0.5897027254104614 + <_> + + <_> + + + + <_>4 18 12 2 -1. + <_>8 18 4 2 3. + 0 + 4.5575071126222610e-003 + 0.4306578934192658 + 1 + <_> + + + + <_>4 10 12 4 -1. + <_>8 10 4 4 3. + 0 + 8.1241987645626068e-003 + 0.7149587273597717 + 0.4345684945583344 + <_> + + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + -4.4612158671952784e-004 + 0.3295974135398865 + 1 + <_> + + + + <_>14 1 2 8 -1. + <_>15 1 1 4 2. + <_>14 5 1 4 2. + 0 + -2.8972938889637589e-004 + 0.5845620036125183 + 0.3526687920093536 + <_> + + <_> + + + + <_>3 4 9 1 -1. + <_>6 4 3 1 3. + 0 + 7.1604831646254752e-006 + 0.4081954956054688 + 1 + <_> + + + + <_>3 3 4 2 -1. + <_>3 4 4 1 2. + 0 + -3.8497708737850189e-004 + 0.4203113019466400 + 0.6634126901626587 + <_> + + <_> + + + + <_>11 15 2 4 -1. + <_>11 17 2 2 2. + 0 + 1.9489860278554261e-004 + 0.3942466974258423 + 1 + <_> + + + + <_>14 13 2 6 -1. + <_>14 15 2 2 3. + 0 + -0.0170838497579098 + 0.2294072061777115 + 0.5238960981369019 + <_> + + <_> + + + + <_>6 6 1 6 -1. + <_>6 9 1 3 2. + 0 + 8.3513697609305382e-004 + 0.3026031851768494 + 1 + <_> + + + + <_>6 10 8 8 -1. + <_>6 14 8 4 2. + 0 + 7.5499608647078276e-004 + 0.6032196283340454 + 0.3412458896636963 + <_> + + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 8.0216713249683380e-003 + 1 + 0.7306240797042847 + <_> + + + + <_>10 11 4 8 -1. + <_>10 15 4 4 2. + 0 + -0.0389305092394352 + 0.3599325120449066 + 0.5234380960464478 + <_> + + <_> + + + + <_>5 11 6 1 -1. + <_>7 11 2 1 3. + 0 + -7.0348767621908337e-005 + 1 + 0.3493758141994476 + <_> + + + + <_>5 4 6 10 -1. + <_>8 4 3 10 2. + 0 + -8.5350573062896729e-003 + 0.2746109068393707 + 0.5626586079597473 + <_> + + <_> + + + + <_>14 2 6 3 -1. + <_>14 3 6 1 3. + 0 + 0.0108544500544667 + 0.5282226204872131 + 1 + <_> + + + + <_>9 12 3 2 -1. + <_>9 13 3 1 2. + 0 + 4.5329501153901219e-004 + 0.4522049129009247 + 0.6054301857948303 + <_> + + <_> + + + + <_>8 1 4 6 -1. + <_>8 3 4 2 3. + 0 + 1.8117150466423482e-004 + 0.3306862115859985 + 1 + <_> + + + + <_>3 5 13 8 -1. + <_>3 9 13 4 2. + 0 + 4.6641560038551688e-004 + 0.1455000042915344 + 0.5384927988052368 + <_> + + <_> + + + + <_>12 5 5 3 -1. + <_>12 6 5 1 3. + 0 + -8.4854792803525925e-003 + 1 + 0.4814155995845795 + <_> + + + + <_>5 14 15 6 -1. + <_>5 16 15 2 3. + 0 + -0.0189343094825745 + 0.3563741147518158 + 0.5405145287513733 + <_> + + <_> + + + + <_>3 5 5 3 -1. + <_>3 6 5 1 3. + 0 + 4.9814549274742603e-003 + 1 + 0.6957743167877197 + <_> + + + + <_>9 14 2 6 -1. + <_>9 14 1 3 2. + <_>10 17 1 3 2. + 0 + 3.4286780282855034e-003 + 0.5050892829895020 + 0.2316994965076447 + <_> + + <_> + + + + <_>9 12 3 2 -1. + <_>9 13 3 1 2. + 0 + 4.4203791185282171e-004 + 1 + 0.6018581986427307 + <_> + + + + <_>9 13 3 2 -1. + <_>9 14 3 1 2. + 0 + 2.3822550429031253e-004 + 0.4755082130432129 + 0.5585237741470337 + <_> + + <_> + + + + <_>0 2 6 3 -1. + <_>0 3 6 1 3. + 0 + -6.4261639490723610e-003 + 0.2282465994358063 + 1 + <_> + + + + <_>0 1 9 11 -1. + <_>3 1 3 11 3. + 0 + 9.9637769162654877e-003 + 0.4040588140487671 + 0.5650169849395752 + <_> + + <_> + + + + <_>8 13 4 6 -1. + <_>10 13 2 3 2. + <_>8 16 2 3 2. + 0 + 0.0136540504172444 + 0.5267739295959473 + 1 + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -9.9892877042293549e-003 + 0.6794049739837647 + 0.4797033965587616 + <_> + + <_> + + + + <_>3 12 14 4 -1. + <_>3 12 7 2 2. + <_>10 14 7 2 2. + 0 + 0.0365586318075657 + 1 + 0.0884257331490517 + <_> + + + + <_>7 14 1 4 -1. + <_>7 16 1 2 2. + 0 + 4.8999379941960797e-005 + 0.4020788073539734 + 0.5457332134246826 + <_> + + <_> + + + + <_>8 13 4 6 -1. + <_>10 13 2 3 2. + <_>8 16 2 3 2. + 0 + 0.0136540504172444 + 0.5267612934112549 + 1 + <_> + + + + <_>10 14 1 3 -1. + <_>10 15 1 1 3. + 0 + 1.8802779959514737e-003 + 0.4806052148342133 + 0.6394364833831787 + <_> + + <_> + + + + <_>8 13 4 6 -1. + <_>8 13 2 3 2. + <_>10 16 2 3 2. + 0 + -0.0136540504172444 + 0.1724810004234314 + 1 + <_> + + + + <_>9 14 1 3 -1. + <_>9 15 1 1 3. + 0 + 1.2778700329363346e-003 + 0.4479824006557465 + 0.6310008764266968 + <_> + + <_> + + + + <_>10 15 2 3 -1. + <_>10 16 2 1 3. + 0 + 9.8843395244330168e-004 + 1 + 0.5948169231414795 + <_> + + + + <_>11 16 1 2 -1. + <_>11 17 1 1 2. + 0 + 1.4511500012304168e-005 + 0.4854174852371216 + 0.5309361219406128 + <_> + + <_> + + + + <_>9 0 2 2 -1. + <_>9 1 2 1 2. + 0 + -2.2775429533794522e-004 + 0.3183631896972656 + 1 + <_> + + + + <_>0 1 5 8 -1. + <_>0 5 5 4 2. + 0 + -0.0147537402808666 + 0.3084976077079773 + 0.5352026224136353 + <_> + + <_> + + + + <_>10 14 2 3 -1. + <_>10 15 2 1 3. + 0 + -3.4148250706493855e-003 + 0.6115326881408691 + 1 + <_> + + + + <_>10 13 2 3 -1. + <_>10 14 2 1 3. + 0 + 7.5806681998074055e-003 + 0.4951646029949188 + 0.7061331272125244 + <_> + + <_> + + + + <_>0 3 16 6 -1. + <_>0 6 16 3 2. + 0 + -5.7734688743948936e-003 + 1 + 0.3754220902919769 + <_> + + + + <_>4 1 2 2 -1. + <_>5 1 1 2 2. + 0 + 7.4033669079653919e-005 + 0.4115517139434815 + 0.5889444947242737 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 8 2 1 3. + 0 + -8.2278084009885788e-003 + 0.0956105664372444 + 1 + <_> + + + + <_>10 8 2 12 -1. + <_>10 12 2 4 3. + 0 + 5.3380909375846386e-003 + 0.5300508737564087 + 0.3961898088455200 + <_> + + <_> + + + + <_>9 7 2 2 -1. + <_>10 7 1 2 2. + 0 + -2.7049109339714050e-003 + 0.6481869220733643 + 1 + <_> + + + + <_>5 0 6 8 -1. + <_>7 0 2 8 3. + 0 + 7.7341338619589806e-003 + 0.5110440254211426 + 0.3121519088745117 + <_> + + <_> + + + + <_>9 7 3 6 -1. + <_>10 7 1 6 3. + 0 + 0.0108866095542908 + 0.4801428914070129 + 1 + <_> + + + + <_>8 12 10 8 -1. + <_>8 16 10 4 2. + 0 + 0.0110386600717902 + 0.5429710149765015 + 0.4162363111972809 + <_> + + <_> + + + + <_>8 7 3 6 -1. + <_>9 7 1 6 3. + 0 + -0.0100541999563575 + 0.7329335212707520 + 1 + <_> + + + + <_>4 7 12 2 -1. + <_>10 7 6 2 2. + 0 + 7.7072880230844021e-003 + 0.5356872081756592 + 0.3455547094345093 + <_> + + <_> + + + + <_>8 6 8 3 -1. + <_>8 6 4 3 2. + 0 + -5.8278098003938794e-004 + 0.3655022084712982 + 1 + <_> + + + + <_>16 15 3 3 -1. + <_>16 16 3 1 3. + 0 + -2.5739220436662436e-003 + 0.3776760101318359 + 0.5391774773597717 + <_> + + <_> + + + + <_>4 6 12 3 -1. + <_>10 6 6 3 2. + 0 + -7.0167761296033859e-003 + 0.4039304852485657 + 1 + <_> + + + + <_>7 8 3 5 -1. + <_>8 8 1 5 3. + 0 + -1.7727289814502001e-003 + 0.6950443983078003 + 0.4981116950511932 + <_> + + <_> + + + + <_>0 10 20 2 -1. + <_>10 10 10 1 2. + <_>0 11 10 1 2. + 0 + -0.0163182895630598 + 1 + 0.5296732783317566 + <_> + + + + <_>11 16 9 4 -1. + <_>14 16 3 4 3. + 0 + -0.0116630000993609 + 0.5842639803886414 + 0.4789502918720245 + <_> + + <_> + + + + <_>0 5 3 4 -1. + <_>1 5 1 4 3. + 0 + 2.5881489273160696e-003 + 1 + 0.6092178821563721 + <_> + + + + <_>8 15 4 2 -1. + <_>8 15 2 1 2. + <_>10 16 2 1 2. + 0 + -3.7328999023884535e-003 + 0.6721742749214172 + 0.4066894054412842 + <_> + + <_> + + + + <_>1 8 19 3 -1. + <_>1 9 19 1 3. + 0 + -1.4355930034071207e-003 + 0.3585087954998016 + 1 + <_> + + + + <_>15 16 3 3 -1. + <_>15 17 3 1 3. + 0 + 1.8340899841859937e-003 + 0.5371158123016357 + 0.4033507108688355 + <_> + + <_> + + + + <_>0 4 20 10 -1. + <_>0 4 10 5 2. + <_>10 9 10 5 2. + 0 + 0.1228028982877731 + 1 + 0.1547572016716003 + <_> + + + + <_>2 14 7 6 -1. + <_>2 16 7 2 3. + 0 + 0.0502287000417709 + 0.5433843731880188 + 0.0842926725745201 + <_> + + <_> + + + + <_>8 6 6 6 -1. + <_>10 6 2 6 3. + 0 + -0.0214370004832745 + 1 + 0.4860053956508637 + <_> + + + + <_>16 4 4 6 -1. + <_>16 6 4 2 3. + 0 + -0.0310096200555563 + 0.1833010017871857 + 0.5207554101943970 + <_> + + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -0.0129737202078104 + 0.7048240900039673 + 1 + <_> + + + + <_>7 13 4 3 -1. + <_>7 14 4 1 3. + 0 + 1.5818020328879356e-003 + 0.4170587062835693 + 0.5865163803100586 + <_> + + <_> + + + + <_>13 13 6 2 -1. + <_>13 14 6 1 2. + 0 + -9.7806248813867569e-003 + 1 + 0.5307918190956116 + <_> + + + + <_>14 12 2 3 -1. + <_>14 13 2 1 3. + 0 + 1.1735740117728710e-003 + 0.5522453188896179 + 0.3507165014743805 + <_> + + <_> + + + + <_>1 13 6 2 -1. + <_>1 14 6 1 2. + 0 + 1.4651629608124495e-003 + 1 + 0.3042651116847992 + <_> + + + + <_>4 12 2 3 -1. + <_>4 13 2 1 3. + 0 + 2.3532148916274309e-003 + 0.5339323282241821 + 0.2806236147880554 + <_> + + <_> + + + + <_>17 4 3 5 -1. + <_>18 4 1 5 3. + 0 + -6.1809681355953217e-003 + 0.6410133242607117 + 1 + <_> + + + + <_>5 5 14 8 -1. + <_>12 5 7 4 2. + <_>5 9 7 4 2. + 0 + 6.5688649192452431e-004 + 0.5620871186256409 + 0.4390318989753723 + <_> + + <_> + + + + <_>6 8 6 5 -1. + <_>8 8 2 5 3. + 0 + 0.0262280106544495 + 1 + 0.6445556879043579 + <_> + + + + <_>0 4 4 6 -1. + <_>0 6 4 2 3. + 0 + -0.0179581101983786 + 0.2002713978290558 + 0.4624665081501007 + <_> + + <_> + + + + <_>9 1 3 6 -1. + <_>10 1 1 6 3. + 0 + -7.6468721963465214e-003 + 1 + 0.5263200998306274 + <_> + + + + <_>10 4 6 3 -1. + <_>10 5 6 1 3. + 0 + -2.7482809964567423e-003 + 0.5873981118202210 + 0.4836600124835968 + <_> + + <_> + + + + <_>8 1 3 6 -1. + <_>9 1 1 6 3. + 0 + 0.0138518502935767 + 1 + 0.1566130965948105 + <_> + + + + <_>4 4 6 3 -1. + <_>4 5 6 1 3. + 0 + 2.6369190309196711e-003 + 0.4270178973674774 + 0.5806660056114197 + <_> + + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + -3.1513599678874016e-003 + 0.6215866208076477 + 1 + <_> + + + + <_>12 11 4 2 -1. + <_>12 12 4 1 2. + 0 + -1.4788460248382762e-005 + 0.5576642751693726 + 0.4122002124786377 + <_> + + <_> + + + + <_>0 2 20 6 -1. + <_>0 2 10 3 2. + <_>10 5 10 3 2. + 0 + -0.0736769884824753 + 0.1536709964275360 + 1 + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + -3.0912780202925205e-003 + 0.6344268918037415 + 0.4507412016391754 + <_> + + <_> + + + + <_>2 10 16 4 -1. + <_>10 10 8 2 2. + <_>2 12 8 2 2. + 0 + 7.9240966588258743e-003 + 0.5457975268363953 + 1 + <_> + + + + <_>3 10 16 6 -1. + <_>11 10 8 3 2. + <_>3 13 8 3 2. + 0 + 8.5778040811419487e-003 + 0.5401657223701477 + 0.3890799880027771 + <_> + + <_> + + + + <_>1 10 16 6 -1. + <_>1 10 8 3 2. + <_>9 13 8 3 2. + 0 + 5.5403169244527817e-003 + 1 + 0.3555611073970795 + <_> + + + + <_>4 7 2 4 -1. + <_>5 7 1 4 2. + 0 + -1.1886510037584230e-004 + 0.5836750268936157 + 0.4274316132068634 + <_> + + <_> + + + + <_>11 16 9 4 -1. + <_>14 16 3 4 3. + 0 + -0.0184083692729473 + 0.5860440135002136 + 1 + <_> + + + + <_>3 16 14 4 -1. + <_>10 16 7 2 2. + <_>3 18 7 2 2. + 0 + -2.3490579333156347e-003 + 0.4498957991600037 + 0.5498198866844177 + <_> + + <_> + + + + <_>0 16 9 4 -1. + <_>3 16 3 4 3. + 0 + -7.6157399453222752e-003 + 1 + 0.4100992977619171 + <_> + + + + <_>1 14 6 6 -1. + <_>1 14 3 3 2. + <_>4 17 3 3 2. + 0 + -3.3190969843417406e-003 + 0.6701378822326660 + 0.4353001117706299 + <_> + + <_> + + + + <_>9 0 2 1 -1. + <_>9 0 1 1 2. + 0 + -9.4642979092895985e-004 + 1 + 0.5391176939010620 + <_> + + + + <_>6 7 8 10 -1. + <_>10 7 4 5 2. + <_>6 12 4 5 2. + 0 + 8.7858550250530243e-003 + 0.5504050254821777 + 0.3990935087203980 + <_> + + <_> + + + + <_>2 15 1 2 -1. + <_>2 16 1 1 2. + 0 + 1.6395459533669055e-004 + 1 + 0.3592933118343353 + <_> + + + + <_>0 14 7 6 -1. + <_>0 16 7 2 3. + 0 + -2.3508940357714891e-003 + 0.4034172892570496 + 0.5806077122688294 + <_> + + <_> + + + + <_>7 8 6 2 -1. + <_>7 9 6 1 2. + 0 + 7.5449963333085179e-005 + 1 + 0.5412384867668152 + <_> + + + + <_>9 2 2 15 -1. + <_>9 7 2 5 3. + 0 + 0.0270184893161058 + 0.4944922924041748 + 0.5589436292648315 + <_> + + <_> + + + + <_>5 6 2 2 -1. + <_>5 7 2 1 2. + 0 + 8.4561208495870233e-004 + 1 + 0.5809218287467957 + <_> + + + + <_>6 6 8 3 -1. + <_>6 7 8 1 3. + 0 + -1.1687109945341945e-003 + 0.4746957123279572 + 0.2845895886421204 + <_> + + <_> + + + + <_>12 13 5 6 -1. + <_>12 15 5 2 3. + 0 + 0.0228975005447865 + 1 + 0.2414411008358002 + <_> + + + + <_>0 0 20 18 -1. + <_>0 9 20 9 2. + 0 + 0.7087926268577576 + 0.5195764899253845 + 0.1030092015862465 + <_> + + <_> + + + + <_>5 1 6 6 -1. + <_>7 1 2 6 3. + 0 + 0.0374838300049305 + 1 + 0.1814638972282410 + <_> + + + + <_>5 1 4 9 -1. + <_>7 1 2 9 2. + 0 + 1.2827500468119979e-003 + 0.4246071875095367 + 0.5707973241806030 + <_> + + <_> + + + + <_>1 19 18 1 -1. + <_>7 19 6 1 3. + 0 + -5.1718312315642834e-003 + 0.6143323183059692 + 1 + <_> + + + + <_>14 16 5 2 -1. + <_>14 17 5 1 2. + 0 + 2.7545939665287733e-003 + 0.5205671191215515 + 0.4220441877841950 + <_> + + <_> + + + + <_>0 5 15 10 -1. + <_>0 10 15 5 2. + 0 + -3.6072919610887766e-003 + 0.3182592093944550 + 1 + <_> + + + + <_>7 15 4 2 -1. + <_>7 15 2 1 2. + <_>9 16 2 1 2. + 0 + -2.5258748792111874e-004 + 0.5710468292236328 + 0.4226093888282776 + <_> + + <_> + + + + <_>14 11 2 2 -1. + <_>14 12 2 1 2. + 0 + -7.0514748804271221e-003 + 1 + 0.5162829756736755 + <_> + + + + <_>9 8 3 3 -1. + <_>9 9 3 1 3. + 0 + -5.4323761723935604e-003 + 0.2666288912296295 + 0.5214679837226868 + <_> + + <_> + + + + <_>4 11 2 2 -1. + <_>4 12 2 1 2. + 0 + -1.4652940080850385e-005 + 1 + 0.3981761038303375 + <_> + + + + <_>8 8 3 3 -1. + <_>8 9 3 1 3. + 0 + -1.8556920113041997e-003 + 0.3322763144969940 + 0.5705834031105042 + <_> + + <_> + + + + <_>9 10 2 3 -1. + <_>9 11 2 1 3. + 0 + 4.7609540633857250e-003 + 1 + 0.6636558175086975 + <_> + + + + <_>8 8 4 3 -1. + <_>8 9 4 1 3. + 0 + 1.5676260227337480e-003 + 0.5505567789077759 + 0.4420661926269531 + <_> + + <_> + + + + <_>1 9 4 10 -1. + <_>1 9 2 5 2. + <_>3 14 2 5 2. + 0 + 5.4239919409155846e-003 + 1 + 0.5959938168525696 + <_> + + + + <_>0 12 6 8 -1. + <_>2 12 2 8 3. + 0 + -6.4692399464547634e-003 + 0.5369594097137451 + 0.3744339942932129 + <_> + + <_> + + + + <_>9 1 4 2 -1. + <_>11 1 2 1 2. + <_>9 2 2 1 2. + 0 + -7.8038539504632354e-004 + 0.4103595018386841 + 1 + <_> + + + + <_>12 13 7 6 -1. + <_>12 15 7 2 3. + 0 + 0.0450864508748055 + 0.5177506804466248 + 0.1878100037574768 + <_> + + <_> + + + + <_>7 0 2 3 -1. + <_>7 1 2 1 3. + 0 + -5.1405387930572033e-003 + 0.2352892011404038 + 1 + <_> + + + + <_>7 14 6 3 -1. + <_>9 14 2 3 3. + 0 + -0.0212361291050911 + 0.1708751022815704 + 0.5424973964691162 + <_> + + <_> + + + + <_>9 6 6 4 -1. + <_>11 6 2 4 3. + 0 + -2.3763340432196856e-003 + 0.5836530923843384 + 1 + <_> + + + + <_>8 10 8 3 -1. + <_>8 10 4 3 2. + 0 + 0.0541225895285606 + 0.5117433071136475 + 0.1865931004285812 + <_> + + <_> + + + + <_>6 10 4 3 -1. + <_>8 10 2 3 2. + 0 + -5.3492980077862740e-004 + 0.5108693242073059 + 1 + <_> + + + + <_>6 8 3 5 -1. + <_>7 8 1 5 3. + 0 + -5.8454048121348023e-004 + 0.4775491058826447 + 0.2439853996038437 + 30.6721305847167970 + 11 + -1 + <_> + + + <_> + + <_> + + + + <_>0 4 8 1 -1. + <_>4 4 4 1 2. + 0 + 3.0031939968466759e-003 + 0.3349649906158447 + 1 + <_> + + + + <_>8 2 2 6 -1. + <_>8 2 1 3 2. + <_>9 5 1 3 2. + 0 + 6.9161207647994161e-004 + 0.4518367946147919 + 0.7289354205131531 + <_> + + <_> + + + + <_>0 7 20 6 -1. + <_>0 9 20 2 3. + 0 + 0.0112127903848886 + 0.2950800955295563 + 1 + <_> + + + + <_>12 10 3 6 -1. + <_>12 13 3 3 2. + 0 + -7.6108198845759034e-004 + 0.5669054985046387 + 0.2830851078033447 + <_> + + <_> + + + + <_>8 15 1 4 -1. + <_>8 17 1 2 2. + 0 + 1.1984579759882763e-004 + 0.4090577960014343 + 1 + <_> + + + + <_>5 16 2 4 -1. + <_>5 18 2 2 2. + 0 + -1.9725349557120353e-004 + 0.6951494216918945 + 0.4637868106365204 + <_> + + <_> + + + + <_>6 2 8 12 -1. + <_>6 6 8 4 3. + 0 + -5.5180420167744160e-003 + 1 + 0.3167675137519836 + <_> + + + + <_>4 7 12 2 -1. + <_>8 7 4 2 3. + 0 + 1.2148249661549926e-003 + 0.3316706120967865 + 0.5396397709846497 + <_> + + <_> + + + + <_>7 0 6 1 -1. + <_>9 0 2 1 3. + 0 + -4.2497441172599792e-003 + 0.2600573897361755 + 1 + <_> + + + + <_>8 11 3 3 -1. + <_>8 12 3 1 3. + 0 + -9.4915721565485001e-003 + 0.7484294772148132 + 0.5073192119598389 + <_> + + <_> + + + + <_>12 11 3 6 -1. + <_>12 14 3 3 2. + 0 + 6.5378600265830755e-004 + 1 + 0.3952010869979858 + <_> + + + + <_>11 2 6 10 -1. + <_>14 2 3 5 2. + <_>11 7 3 5 2. + 0 + -4.9741100519895554e-004 + 0.5880274772644043 + 0.3552120029926300 + <_> + + <_> + + + + <_>5 7 10 12 -1. + <_>5 7 5 6 2. + <_>10 13 5 6 2. + 0 + -0.0430792495608330 + 0.2434878051280975 + 1 + <_> + + + + <_>4 4 2 10 -1. + <_>4 9 2 5 2. + 0 + -5.1999092102050781e-004 + 0.3195562958717346 + 0.5585454702377319 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 7 1 3 2. + 0 + -4.5451628975570202e-003 + 1 + 0.4845289885997772 + <_> + + + + <_>11 9 6 2 -1. + <_>11 9 3 2 2. + 0 + -7.9610403627157211e-003 + 0.3801181018352509 + 0.5358511805534363 + <_> + + <_> + + + + <_>4 7 2 2 -1. + <_>5 7 1 2 2. + 0 + -3.1919340835884213e-004 + 1 + 0.4356329143047333 + <_> + + + + <_>0 2 4 6 -1. + <_>0 4 4 2 3. + 0 + -0.0192238893359900 + 0.2613066136837006 + 0.6155496239662170 + <_> + + <_> + + + + <_>10 7 3 4 -1. + <_>11 7 1 4 3. + 0 + -1.3076990144327283e-003 + 0.5942062139511108 + 1 + <_> + + + + <_>9 7 3 5 -1. + <_>10 7 1 5 3. + 0 + 0.0198250394314528 + 0.4945428073406220 + 0.7384855151176453 + <_> + + <_> + + + + <_>9 1 1 3 -1. + <_>9 2 1 1 3. + 0 + -2.2013280540704727e-003 + 0.2214481979608536 + 1 + <_> + + + + <_>0 6 16 6 -1. + <_>0 6 8 3 2. + <_>8 9 8 3 2. + 0 + -7.8596705570816994e-003 + 0.3600977063179016 + 0.5298550128936768 + <_> + + <_> + + + + <_>10 15 3 3 -1. + <_>10 16 3 1 3. + 0 + 1.4142199652269483e-003 + 1 + 0.5776566267013550 + <_> + + + + <_>9 14 4 3 -1. + <_>9 15 4 1 3. + 0 + -0.0112327598035336 + 0.6934456825256348 + 0.4827207028865814 + <_> + + <_> + + + + <_>3 2 6 10 -1. + <_>3 2 3 5 2. + <_>6 7 3 5 2. + 0 + 2.9746301006525755e-003 + 1 + 0.3216677010059357 + <_> + + + + <_>3 0 14 2 -1. + <_>3 1 14 1 2. + 0 + 5.3283828310668468e-004 + 0.3962500095367432 + 0.5680363774299622 + <_> + + <_> + + + + <_>9 14 3 3 -1. + <_>9 15 3 1 3. + 0 + 0.0101052597165108 + 1 + 0.7567418217658997 + <_> + + + + <_>10 15 3 3 -1. + <_>10 16 3 1 3. + 0 + -0.0116536999121308 + 0.6523556709289551 + 0.5027053952217102 + <_> + + <_> + + + + <_>9 13 2 6 -1. + <_>9 16 2 3 2. + 0 + -7.0609981194138527e-003 + 0.2538770139217377 + 1 + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + 2.2343141026794910e-003 + 0.4387277066707611 + 0.6177632212638855 + <_> + + <_> + + + + <_>12 11 3 6 -1. + <_>12 14 3 3 2. + 0 + -0.0298022795468569 + 1 + 0.5201140046119690 + <_> + + + + <_>8 12 5 2 -1. + <_>8 13 5 1 2. + 0 + 1.1611840454861522e-003 + 0.4647909998893738 + 0.6184254884719849 + <_> + + <_> + + + + <_>5 11 3 6 -1. + <_>5 14 3 3 2. + 0 + 9.4824447296559811e-004 + 1 + 0.3040994107723236 + <_> + + + + <_>8 12 3 2 -1. + <_>8 13 3 1 2. + 0 + 4.1284630424343050e-004 + 0.4518808126449585 + 0.6245782971382141 + <_> + + <_> + + + + <_>11 13 7 6 -1. + <_>11 15 7 2 3. + 0 + -0.0312035400420427 + 0.2788935899734497 + 1 + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + 2.7652881108224392e-003 + 0.4698500037193298 + 0.6502454280853272 + <_> + + <_> + + + + <_>3 13 14 4 -1. + <_>3 13 7 2 2. + <_>10 15 7 2 2. + 0 + 0.0256447792053223 + 1 + 0.1805171072483063 + <_> + + + + <_>8 14 4 6 -1. + <_>8 14 2 3 2. + <_>10 17 2 3 2. + 0 + -7.5331530533730984e-003 + 0.3208068907260895 + 0.5522022843360901 + <_> + + <_> + + + + <_>8 15 4 3 -1. + <_>8 16 4 1 3. + 0 + 3.2047149725258350e-003 + 1 + 0.6436933875083923 + <_> + + + + <_>7 16 6 2 -1. + <_>9 16 2 2 3. + 0 + -2.4282479716930538e-004 + 0.5676705241203308 + 0.4509103894233704 + <_> + + <_> + + + + <_>7 7 6 2 -1. + <_>7 8 6 1 2. + 0 + -6.1979342717677355e-004 + 0.3122146129608154 + 1 + <_> + + + + <_>3 9 13 3 -1. + <_>3 10 13 1 3. + 0 + -8.0101029016077518e-004 + 0.2965193986892700 + 0.5230494737625122 + <_> + + <_> + + + + <_>9 8 3 4 -1. + <_>9 10 3 2 2. + 0 + -9.1816839994862676e-004 + 1 + 0.5464711785316467 + <_> + + + + <_>8 10 4 3 -1. + <_>8 11 4 1 3. + 0 + 1.2239529751241207e-003 + 0.4618502855300903 + 0.5679548978805542 + <_> + + <_> + + + + <_>7 7 3 4 -1. + <_>8 7 1 4 3. + 0 + -6.8743730662390590e-004 + 0.5430880188941956 + 1 + <_> + + + + <_>8 7 3 5 -1. + <_>9 7 1 5 3. + 0 + -1.8252469599246979e-003 + 0.5433623194694519 + 0.3385221064090729 + <_> + + <_> + + + + <_>12 3 3 4 -1. + <_>13 3 1 4 3. + 0 + -7.4570789001882076e-003 + 1 + 0.5265594720840454 + <_> + + + + <_>9 7 2 3 -1. + <_>9 7 1 3 2. + 0 + 5.3775748237967491e-003 + 0.4857215881347656 + 0.6815124154090881 + <_> + + <_> + + + + <_>5 3 3 4 -1. + <_>6 3 1 4 3. + 0 + 3.7602309603244066e-003 + 1 + 0.2832160890102387 + <_> + + + + <_>3 7 12 1 -1. + <_>7 7 4 1 3. + 0 + 8.7752222316339612e-004 + 0.3966830968856812 + 0.5512480735778809 + <_> + + <_> + + + + <_>12 5 3 3 -1. + <_>12 6 3 1 3. + 0 + 5.5084479972720146e-003 + 1 + 0.6784620285034180 + <_> + + + + <_>11 2 6 2 -1. + <_>11 3 6 1 2. + 0 + -7.5949047459289432e-004 + 0.3906503021717072 + 0.5457202792167664 + <_> + + <_> + + + + <_>3 2 14 2 -1. + <_>3 2 7 1 2. + <_>10 3 7 1 2. + 0 + 1.6352660022675991e-003 + 1 + 0.3640204071998596 + <_> + + + + <_>6 1 7 14 -1. + <_>6 8 7 7 2. + 0 + -1.2750849418807775e-004 + 0.5829724073410034 + 0.4194979965686798 + <_> + + <_> + + + + <_>8 0 12 5 -1. + <_>8 0 6 5 2. + 0 + 0.0220676101744175 + 0.4606702923774719 + 1 + <_> + + + + <_>1 9 18 1 -1. + <_>7 9 6 1 3. + 0 + -0.0192037895321846 + 0.3261483013629913 + 0.5236080884933472 + <_> + + <_> + + + + <_>0 0 10 5 -1. + <_>5 0 5 5 2. + 0 + -0.0129981096833944 + 0.7022112011909485 + 1 + <_> + + + + <_>2 5 8 15 -1. + <_>2 10 8 5 3. + 0 + -3.1332690268754959e-003 + 0.2870470881462097 + 0.5076476931571960 + <_> + + <_> + + + + <_>12 5 3 3 -1. + <_>12 6 3 1 3. + 0 + -5.2937557920813560e-003 + 1 + 0.4709520936012268 + <_> + + + + <_>13 4 2 3 -1. + <_>13 5 2 1 3. + 0 + 2.1857069805264473e-003 + 0.4708291888237000 + 0.6169841885566711 + <_> + + <_> + + + + <_>2 15 4 3 -1. + <_>2 16 4 1 3. + 0 + -4.5750709250569344e-003 + 0.3114252984523773 + 1 + <_> + + + + <_>5 6 10 3 -1. + <_>10 6 5 3 2. + 0 + -0.0451521389186382 + 0.1851435005664825 + 0.5504814982414246 + <_> + + <_> + + + + <_>11 6 2 2 -1. + <_>12 6 1 1 2. + <_>11 7 1 1 2. + 0 + -2.7783559635281563e-003 + 1 + 0.4937348067760468 + <_> + + + + <_>12 4 4 3 -1. + <_>12 5 4 1 3. + 0 + -2.5752480141818523e-003 + 0.6152948141098023 + 0.4735499918460846 + <_> + + <_> + + + + <_>7 6 2 2 -1. + <_>7 6 1 1 2. + <_>8 7 1 1 2. + 0 + 1.1614130344241858e-003 + 1 + 0.6510571837425232 + <_> + + + + <_>4 4 4 3 -1. + <_>4 5 4 1 3. + 0 + 2.3350189439952374e-003 + 0.4088341891765595 + 0.5684152245521545 + <_> + + <_> + + + + <_>11 4 3 3 -1. + <_>12 4 1 3 3. + 0 + 3.8499289657920599e-003 + 1 + 0.3025828897953033 + <_> + + + + <_>9 3 2 1 -1. + <_>9 3 1 1 2. + 0 + 2.4529630318284035e-003 + 0.5232502818107605 + 0.2017620950937271 + <_> + + <_> + + + + <_>4 5 5 3 -1. + <_>4 6 5 1 3. + 0 + 3.6731390282511711e-003 + 1 + 0.6428425908088684 + <_> + + + + <_>4 6 4 3 -1. + <_>4 7 4 1 3. + 0 + 2.1937100682407618e-003 + 0.4328865110874176 + 0.6420509815216065 + <_> + + <_> + + + + <_>11 4 3 3 -1. + <_>12 4 1 3 3. + 0 + -6.4666871912777424e-003 + 1 + 0.5254065990447998 + <_> + + + + <_>8 8 4 3 -1. + <_>8 9 4 1 3. + 0 + -5.7186251506209373e-003 + 0.2490984052419663 + 0.5287619233131409 + <_> + + <_> + + + + <_>6 4 3 3 -1. + <_>7 4 1 3 3. + 0 + 9.9941878579556942e-004 + 1 + 0.3329795897006989 + <_> + + + + <_>4 14 1 3 -1. + <_>4 15 1 1 3. + 0 + -7.8276498243212700e-004 + 0.3598344922065735 + 0.5498340725898743 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 7 1 3 2. + 0 + 4.3231188319623470e-003 + 0.4818705022335053 + 1 + <_> + + + + <_>17 0 3 2 -1. + <_>17 1 3 1 2. + 0 + 4.0838290005922318e-003 + 0.5266330242156982 + 0.3105789124965668 + <_> + + <_> + + + + <_>8 10 2 9 -1. + <_>8 13 2 3 3. + 0 + 3.0515898833982646e-004 + 1 + 0.3995291888713837 + <_> + + + + <_>0 8 18 2 -1. + <_>0 9 18 1 2. + 0 + 1.2640280183404684e-003 + 0.3228437900543213 + 0.5819215178489685 + <_> + + <_> + + + + <_>9 15 2 3 -1. + <_>9 16 2 1 3. + 0 + -0.0101526603102684 + 0.8026071190834045 + 1 + <_> + + + + <_>8 7 4 3 -1. + <_>8 8 4 1 3. + 0 + -2.6863690000027418e-003 + 0.3875617086887360 + 0.5466570854187012 + <_> + + <_> + + + + <_>1 14 6 6 -1. + <_>1 14 3 3 2. + <_>4 17 3 3 2. + 0 + -9.0515613555908203e-003 + 1 + 0.4372057914733887 + <_> + + + + <_>0 18 6 2 -1. + <_>0 19 6 1 2. + 0 + -6.3204211182892323e-003 + 0.1126551032066345 + 0.6395416259765625 + <_> + + <_> + + + + <_>12 9 4 3 -1. + <_>12 9 2 3 2. + 0 + 2.6117300149053335e-003 + 0.5423989295959473 + 1 + <_> + + + + <_>9 8 3 8 -1. + <_>10 8 1 8 3. + 0 + 0.0143390195444226 + 0.4979273080825806 + 0.6042236089706421 + <_> + + <_> + + + + <_>4 9 4 3 -1. + <_>6 9 2 3 2. + 0 + 2.8452780097723007e-003 + 1 + 0.3491092026233673 + <_> + + + + <_>4 18 6 1 -1. + <_>6 18 2 1 3. + 0 + 1.4783289771003183e-005 + 0.4195067882537842 + 0.5775966048240662 + <_> + + <_> + + + + <_>9 7 3 2 -1. + <_>10 7 1 2 3. + 0 + 8.1814555451273918e-003 + 0.4885987043380737 + 1 + <_> + + + + <_>6 7 8 12 -1. + <_>10 7 4 6 2. + <_>6 13 4 6 2. + 0 + 6.6321990452706814e-003 + 0.5444468259811401 + 0.4420995116233826 + <_> + + <_> + + + + <_>8 7 3 2 -1. + <_>9 7 1 2 3. + 0 + -2.2483461070805788e-003 + 0.6699792146682739 + 1 + <_> + + + + <_>8 7 3 6 -1. + <_>9 7 1 6 3. + 0 + 0.0123745603486896 + 0.4478605985641480 + 0.6564893722534180 + <_> + + <_> + + + + <_>3 16 14 4 -1. + <_>10 16 7 2 2. + <_>3 18 7 2 2. + 0 + -6.6516688093543053e-003 + 1 + 0.5511878728866577 + <_> + + + + <_>1 14 18 4 -1. + <_>10 14 9 2 2. + <_>1 16 9 2 2. + 0 + -8.5750613361597061e-003 + 0.4017445147037506 + 0.5405536293983460 + <_> + + <_> + + + + <_>8 7 3 3 -1. + <_>8 8 3 1 3. + 0 + 6.5078441984951496e-003 + 1 + 0.2294393032789230 + <_> + + + + <_>0 4 20 12 -1. + <_>0 4 10 6 2. + <_>10 10 10 6 2. + 0 + 0.0286752097308636 + 0.5177900195121765 + 0.3567756116390228 + <_> + + <_> + + + + <_>5 5 10 12 -1. + <_>10 5 5 6 2. + <_>5 11 5 6 2. + 0 + 7.0673860609531403e-003 + 0.5564699769020081 + 1 + <_> + + + + <_>10 2 4 7 -1. + <_>10 2 2 7 2. + 0 + 1.2367829913273454e-003 + 0.3627698123455048 + 0.5572413802146912 + <_> + + <_> + + + + <_>8 11 4 3 -1. + <_>8 12 4 1 3. + 0 + 7.4818679131567478e-003 + 1 + 0.6784911155700684 + <_> + + + + <_>8 12 3 3 -1. + <_>8 13 3 1 3. + 0 + 4.7109839506447315e-003 + 0.4121252894401550 + 0.6072235703468323 + <_> + + <_> + + + + <_>13 13 5 6 -1. + <_>13 15 5 2 3. + 0 + -6.9405790418386459e-003 + 1 + 0.5459766983985901 + <_> + + + + <_>7 0 6 6 -1. + <_>9 0 2 6 3. + 0 + 0.0333020985126495 + 0.5276706814765930 + 0.2374915927648544 + <_> + + <_> + + + + <_>2 13 5 6 -1. + <_>2 15 5 2 3. + 0 + 0.0361046306788921 + 1 + 0.0724927932024002 + <_> + + + + <_>0 4 2 12 -1. + <_>0 4 1 6 2. + <_>1 10 1 6 2. + 0 + 0.0196746494621038 + 0.4626345932483673 + 0.8208963274955750 + <_> + + <_> + + + + <_>9 19 3 1 -1. + <_>10 19 1 1 3. + 0 + 3.4766150638461113e-003 + 0.5208731889724731 + 1 + <_> + + + + <_>18 0 2 6 -1. + <_>18 2 2 2 3. + 0 + 1.3987369602546096e-003 + 0.5484414100646973 + 0.4230034947395325 + <_> + + <_> + + + + <_>0 3 1 6 -1. + <_>0 5 1 2 3. + 0 + 4.0974249131977558e-003 + 1 + 0.2780553102493286 + <_> + + + + <_>0 0 3 6 -1. + <_>0 2 3 2 3. + 0 + 2.6973790954798460e-003 + 0.5403831005096436 + 0.3790988922119141 + <_> + + <_> + + + + <_>17 2 3 7 -1. + <_>18 2 1 7 3. + 0 + -5.6591699831187725e-003 + 1 + 0.4798336029052734 + <_> + + + + <_>10 3 4 7 -1. + <_>10 3 2 7 2. + 0 + 3.9460969856008887e-004 + 0.3766950070858002 + 0.5429229140281677 + <_> + + <_> + + + + <_>0 2 3 7 -1. + <_>1 2 1 7 3. + 0 + 2.1750570740550756e-003 + 1 + 0.6207162737846375 + <_> + + + + <_>6 2 4 8 -1. + <_>8 2 2 8 2. + 0 + 1.4614439569413662e-003 + 0.3357945084571838 + 0.5142632126808167 + <_> + + <_> + + + + <_>13 0 1 4 -1. + <_>13 2 1 2 2. + 0 + -5.3006567759439349e-004 + 1 + 0.5344640016555786 + <_> + + + + <_>5 1 12 5 -1. + <_>9 1 4 5 3. + 0 + 0.1486930996179581 + 0.5159608125686646 + 0.2561823129653931 + <_> + + <_> + + + + <_>6 0 1 4 -1. + <_>6 2 1 2 2. + 0 + -5.8816498494707048e-005 + 1 + 0.5123091936111450 + <_> + + + + <_>3 1 12 5 -1. + <_>7 1 4 5 3. + 0 + -1.6275369562208652e-003 + 0.6017646193504334 + 0.3109371960163117 + <_> + + <_> + + + + <_>9 12 3 8 -1. + <_>10 12 1 8 3. + 0 + -0.0128818098455668 + 0.2712287008762360 + 1 + <_> + + + + <_>7 13 6 1 -1. + <_>9 13 2 1 3. + 0 + 9.4982917653396726e-004 + 0.5442442297935486 + 0.4028888046741486 + <_> + + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + -0.0123159997165203 + 1 + 0.4736065864562988 + <_> + + + + <_>5 16 7 3 -1. + <_>5 17 7 1 3. + 0 + 9.0286601334810257e-003 + 0.7451434731483460 + 0.3487991988658905 + <_> + + <_> + + + + <_>0 12 20 6 -1. + <_>0 14 20 2 3. + 0 + -0.0868761166930199 + 0.2290333062410355 + 1 + <_> + + + + <_>4 18 14 2 -1. + <_>4 19 14 1 2. + 0 + -1.5107560102478601e-005 + 0.5517889857292175 + 0.4393149018287659 + <_> + + <_> + + + + <_>8 12 3 8 -1. + <_>9 12 1 8 3. + 0 + -0.0174576602876186 + 0.0901679024100304 + 1 + <_> + + + + <_>7 13 3 3 -1. + <_>7 14 3 1 3. + 0 + -2.5219470262527466e-003 + 0.6233540177345276 + 0.4789459109306335 + <_> + + <_> + + + + <_>5 5 12 10 -1. + <_>11 5 6 5 2. + <_>5 10 6 5 2. + 0 + 1.0656520025804639e-003 + 0.5489696264266968 + 1 + <_> + + + + <_>8 1 5 10 -1. + <_>8 6 5 5 2. + 0 + -4.2540300637483597e-003 + 0.5579808950424194 + 0.4375877976417542 + <_> + + <_> + + + + <_>5 4 9 12 -1. + <_>5 10 9 6 2. + 0 + -9.0349102392792702e-003 + 0.3579156100749970 + 1 + <_> + + + + <_>7 13 6 6 -1. + <_>7 15 6 2 3. + 0 + -1.5230999561026692e-003 + 0.5613660216331482 + 0.3939043879508972 + <_> + + <_> + + + + <_>8 4 5 16 -1. + <_>8 12 5 8 2. + 0 + 2.8441150207072496e-003 + 1 + 0.3901554942131043 + <_> + + + + <_>8 12 4 6 -1. + <_>8 15 4 3 2. + 0 + -3.2824429217725992e-003 + 0.4528619050979614 + 0.5441343188285828 + <_> + + <_> + + + + <_>7 13 2 2 -1. + <_>7 13 1 1 2. + <_>8 14 1 1 2. + 0 + 3.2161718991119415e-005 + 1 + 0.5803111791610718 + <_> + + + + <_>7 12 2 2 -1. + <_>7 12 1 1 2. + <_>8 13 1 1 2. + 0 + 3.0118400900391862e-005 + 0.3336850106716156 + 0.5504856109619141 + <_> + + <_> + + + + <_>18 0 2 14 -1. + <_>18 0 1 14 2. + 0 + -5.6150099262595177e-003 + 0.6124789118766785 + 1 + <_> + + + + <_>12 11 7 2 -1. + <_>12 12 7 1 2. + 0 + -0.0173892099410295 + 0.0872716307640076 + 0.5204588174819946 + <_> + + <_> + + + + <_>1 18 1 2 -1. + <_>1 19 1 1 2. + 0 + -4.4361080654198304e-005 + 0.3935329020023346 + 1 + <_> + + + + <_>2 18 1 2 -1. + <_>2 19 1 1 2. + 0 + 1.0354899859521538e-004 + 0.5918853878974915 + 0.4119614064693451 + <_> + + <_> + + + + <_>9 7 2 1 -1. + <_>9 7 1 1 2. + 0 + 1.5939630102366209e-003 + 0.4839623868465424 + 1 + <_> + + + + <_>9 6 2 3 -1. + <_>9 6 1 3 2. + 0 + 2.5440789759159088e-003 + 0.4787364900112152 + 0.6360663175582886 + <_> + + <_> + + + + <_>3 1 2 2 -1. + <_>4 1 1 2 2. + 0 + 1.5083180187502876e-005 + 0.4231117069721222 + 1 + <_> + + + + <_>3 0 3 2 -1. + <_>3 1 3 1 2. + 0 + -9.9282202427275479e-005 + 0.4274589121341705 + 0.6094048023223877 + <_> + + <_> + + + + <_>12 10 3 4 -1. + <_>12 12 3 2 2. + 0 + 5.5371708003804088e-004 + 1 + 0.4271987974643707 + <_> + + + + <_>7 7 8 2 -1. + <_>7 8 8 1 2. + 0 + 1.9186759600415826e-003 + 0.4497107863426209 + 0.5549122095108032 + <_> + + <_> + + + + <_>8 8 3 4 -1. + <_>8 10 3 2 2. + 0 + -5.0764222396537662e-004 + 1 + 0.5477195978164673 + <_> + + + + <_>7 12 6 3 -1. + <_>7 13 6 1 3. + 0 + 1.7236480489373207e-003 + 0.2882922887802124 + 0.5615127086639404 + 34.6770782470703120 + 12 + -1 + <_> + + + <_> + + <_> + + + + <_>0 2 10 3 -1. + <_>5 2 5 3 2. + 0 + 0.0130921695381403 + 0.3338870108127594 + 1 + <_> + + + + <_>0 1 20 6 -1. + <_>0 3 20 2 3. + 0 + 4.1446479735895991e-004 + 0.3099352121353149 + 0.6677492260932922 + <_> + + <_> + + + + <_>7 6 6 3 -1. + <_>9 6 2 3 3. + 0 + 0.0218357294797897 + 0.4369049072265625 + 1 + <_> + + + + <_>3 7 14 4 -1. + <_>3 9 14 2 2. + 0 + 0.0483239404857159 + 0.4301724135875702 + 0.6153885126113892 + <_> + + <_> + + + + <_>5 7 3 6 -1. + <_>5 9 3 2 3. + 0 + 1.6091950237751007e-003 + 0.3387326002120972 + 1 + <_> + + + + <_>8 8 3 12 -1. + <_>8 12 3 4 3. + 0 + 1.3469760306179523e-003 + 0.6248713731765747 + 0.3594130873680115 + <_> + + <_> + + + + <_>9 17 6 2 -1. + <_>12 17 3 1 2. + <_>9 18 3 1 2. + 0 + 1.7729059618432075e-004 + 0.3868424892425537 + 1 + <_> + + + + <_>10 17 4 3 -1. + <_>10 18 4 1 3. + 0 + 3.6743620876222849e-004 + 0.4409345090389252 + 0.5476474165916443 + <_> + + <_> + + + + <_>4 2 4 2 -1. + <_>4 3 4 1 2. + 0 + -1.2352119665592909e-003 + 0.3260171115398407 + 1 + <_> + + + + <_>7 3 6 14 -1. + <_>9 3 2 14 3. + 0 + 1.1705530341714621e-003 + 0.4111348986625671 + 0.6088163852691650 + <_> + + <_> + + + + <_>15 13 1 6 -1. + <_>15 16 1 3 2. + 0 + -2.9695429475395940e-005 + 1 + 0.4269422888755798 + <_> + + + + <_>13 14 2 6 -1. + <_>13 16 2 2 3. + 0 + 2.7050738572143018e-004 + 0.4306466877460480 + 0.5810514092445374 + <_> + + <_> + + + + <_>4 11 5 6 -1. + <_>4 14 5 3 2. + 0 + -7.9626210208516568e-005 + 1 + 0.3669143021106720 + <_> + + + + <_>4 17 4 2 -1. + <_>6 17 2 2 2. + 0 + 3.3152441028505564e-004 + 0.4610663950443268 + 0.6290590167045593 + <_> + + <_> + + + + <_>0 6 20 2 -1. + <_>0 6 10 2 2. + 0 + -0.0523058287799358 + 1 + 0.5328689813613892 + <_> + + + + <_>6 5 10 12 -1. + <_>11 5 5 6 2. + <_>6 11 5 6 2. + 0 + 0.0268804691731930 + 0.5213261246681213 + 0.3231219947338104 + <_> + + <_> + + + + <_>4 0 2 12 -1. + <_>4 0 1 6 2. + <_>5 6 1 6 2. + 0 + -2.4203000066336244e-004 + 1 + 0.3568570017814636 + <_> + + + + <_>4 1 6 2 -1. + <_>6 1 2 2 3. + 0 + -1.6424639616161585e-003 + 0.3440661132335663 + 0.5625604987144470 + <_> + + <_> + + + + <_>13 7 2 1 -1. + <_>13 7 1 1 2. + 0 + -2.6830288697965443e-004 + 1 + 0.4561173021793366 + <_> + + + + <_>5 5 15 6 -1. + <_>5 7 15 2 3. + 0 + -2.2649629972875118e-003 + 0.5321351885795593 + 0.3674154877662659 + <_> + + <_> + + + + <_>1 10 18 2 -1. + <_>1 10 9 1 2. + <_>10 11 9 1 2. + 0 + 0.0156272090971470 + 1 + 0.2029353976249695 + <_> + + + + <_>1 6 15 7 -1. + <_>6 6 5 7 3. + 0 + 0.1621132045984268 + 0.5563033223152161 + 0.2618849873542786 + <_> + + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + -3.7391691002994776e-003 + 0.6062194705009460 + 1 + <_> + + + + <_>9 14 3 3 -1. + <_>9 15 3 1 3. + 0 + -2.0878419745713472e-003 + 0.5950763821601868 + 0.4545117020606995 + <_> + + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + 2.3334210272878408e-003 + 1 + 0.6435524225234985 + <_> + + + + <_>8 13 3 2 -1. + <_>8 14 3 1 2. + 0 + 6.5116386394947767e-005 + 0.3520734012126923 + 0.5179778933525085 + <_> + + <_> + + + + <_>15 14 5 3 -1. + <_>15 15 5 1 3. + 0 + 7.4625718407332897e-003 + 0.5326688289642334 + 1 + <_> + + + + <_>0 14 20 1 -1. + <_>0 14 10 1 2. + 0 + -0.0220326893031597 + 0.3491981029510498 + 0.5429236888885498 + <_> + + <_> + + + + <_>0 14 6 3 -1. + <_>0 15 6 1 3. + 0 + -8.3081610500812531e-003 + 0.2084023058414459 + 1 + <_> + + + + <_>5 3 4 2 -1. + <_>5 4 4 1 2. + 0 + -4.3259368976578116e-004 + 0.3965272009372711 + 0.5425453782081604 + <_> + + <_> + + + + <_>0 6 20 1 -1. + <_>0 6 10 1 2. + 0 + -0.0322092287242413 + 1 + 0.5306411981582642 + <_> + + + + <_>6 3 10 14 -1. + <_>11 3 5 7 2. + <_>6 10 5 7 2. + 0 + -9.0424838708713651e-004 + 0.5450385808944702 + 0.4256696999073029 + <_> + + <_> + + + + <_>8 12 4 2 -1. + <_>8 13 4 1 2. + 0 + 2.2727500181645155e-003 + 1 + 0.5968611240386963 + <_> + + + + <_>6 3 8 6 -1. + <_>6 3 4 3 2. + <_>10 6 4 3 2. + 0 + 5.9820008464157581e-003 + 0.4758140146732330 + 0.3150944113731384 + <_> + + <_> + + + + <_>13 7 2 1 -1. + <_>13 7 1 1 2. + 0 + -5.8856618124991655e-004 + 1 + 0.4847748875617981 + <_> + + + + <_>6 3 10 14 -1. + <_>11 3 5 7 2. + <_>6 10 5 7 2. + 0 + -8.8227191008627415e-004 + 0.5426316261291504 + 0.4338341057300568 + <_> + + <_> + + + + <_>5 7 2 1 -1. + <_>6 7 1 1 2. + 0 + -7.4473457061685622e-005 + 1 + 0.4287509918212891 + <_> + + + + <_>4 3 10 14 -1. + <_>4 3 5 7 2. + <_>9 10 5 7 2. + 0 + 3.9148979703895748e-004 + 0.6345185041427612 + 0.4101851880550385 + <_> + + <_> + + + + <_>9 7 2 2 -1. + <_>9 7 1 2 2. + 0 + -3.6939629353582859e-003 + 1 + 0.4849104881286621 + <_> + + + + <_>0 3 20 1 -1. + <_>0 3 10 1 2. + 0 + -0.0112078497186303 + 0.4146336913108826 + 0.5471264123916626 + <_> + + <_> + + + + <_>2 1 10 3 -1. + <_>2 2 10 1 3. + 0 + -0.0103374095633626 + 0.2877183854579926 + 1 + <_> + + + + <_>9 7 2 2 -1. + <_>10 7 1 2 2. + 0 + 3.6883640568703413e-003 + 0.5101901888847351 + 0.7216951251029968 + <_> + + <_> + + + + <_>9 17 3 2 -1. + <_>10 17 1 2 3. + 0 + -3.8984280545264482e-003 + 1 + 0.5276182293891907 + <_> + + + + <_>9 7 3 6 -1. + <_>10 7 1 6 3. + 0 + -5.9986729174852371e-003 + 0.6618459820747376 + 0.4841631054878235 + <_> + + <_> + + + + <_>8 17 3 2 -1. + <_>9 17 1 2 3. + 0 + 4.5043681748211384e-003 + 1 + 0.1874157935380936 + <_> + + + + <_>8 7 3 6 -1. + <_>9 7 1 6 3. + 0 + 0.0177995301783085 + 0.4616934955120087 + 0.7088965773582459 + <_> + + <_> + + + + <_>16 3 4 6 -1. + <_>16 5 4 2 3. + 0 + -0.0184625703841448 + 0.3001979887485504 + 1 + <_> + + + + <_>15 6 2 12 -1. + <_>16 6 1 6 2. + <_>15 12 1 6 2. + 0 + 1.4931300029275008e-005 + 0.4561808109283447 + 0.5610787868499756 + <_> + + <_> + + + + <_>1 4 18 10 -1. + <_>1 4 9 5 2. + <_>10 9 9 5 2. + 0 + -0.0860212296247482 + 0.2341700941324234 + 1 + <_> + + + + <_>9 4 2 4 -1. + <_>9 6 2 2 2. + 0 + -6.0818758356617764e-005 + 0.5672286152839661 + 0.4199964106082916 + <_> + + <_> + + + + <_>12 5 3 2 -1. + <_>12 6 3 1 2. + 0 + 1.2670679716393352e-003 + 1 + 0.6207482218742371 + <_> + + + + <_>5 12 10 4 -1. + <_>5 14 10 2 2. + 0 + 1.3699879636988044e-003 + 0.5394958853721619 + 0.3823862969875336 + <_> + + <_> + + + + <_>5 5 3 2 -1. + <_>5 6 3 1 2. + 0 + 3.3162781037390232e-003 + 1 + 0.7061681151390076 + <_> + + + + <_>4 6 12 6 -1. + <_>8 6 4 6 3. + 0 + -1.4532039640471339e-003 + 0.3065513074398041 + 0.4827373027801514 + <_> + + <_> + + + + <_>14 4 6 6 -1. + <_>14 6 6 2 3. + 0 + -0.0714920610189438 + 1 + 0.5193122029304504 + <_> + + + + <_>16 0 4 6 -1. + <_>18 0 2 3 2. + <_>16 3 2 3 2. + 0 + 1.9857978913933039e-003 + 0.4642435014247894 + 0.5807694792747498 + <_> + + <_> + + + + <_>0 4 6 6 -1. + <_>0 6 6 2 3. + 0 + 6.2516499310731888e-003 + 1 + 0.2949813902378082 + <_> + + + + <_>0 0 4 6 -1. + <_>0 0 2 3 2. + <_>2 3 2 3 2. + 0 + 2.7005500160157681e-003 + 0.4585886895656586 + 0.6022353768348694 + <_> + + <_> + + + + <_>12 0 8 5 -1. + <_>12 0 4 5 2. + 0 + 0.0111303897574544 + 0.4357841014862061 + 1 + <_> + + + + <_>16 0 4 17 -1. + <_>16 0 2 17 2. + 0 + 0.0150928497314453 + 0.4561539888381958 + 0.6119061708450317 + <_> + + <_> + + + + <_>1 0 18 20 -1. + <_>7 0 6 20 3. + 0 + -0.0279433000832796 + 0.6537144184112549 + 1 + <_> + + + + <_>6 0 2 5 -1. + <_>7 0 1 5 2. + 0 + 4.4036991312168539e-005 + 0.3474723100662231 + 0.5336967706680298 + <_> + + <_> + + + + <_>0 6 20 1 -1. + <_>0 6 10 1 2. + 0 + -0.0122327702119946 + 0.3731676042079926 + 1 + <_> + + + + <_>8 7 6 4 -1. + <_>10 7 2 4 3. + 0 + -6.8591412855312228e-004 + 0.5717229247093201 + 0.4793379008769989 + <_> + + <_> + + + + <_>1 1 16 4 -1. + <_>1 1 8 2 2. + <_>9 3 8 2 2. + 0 + -3.8992990739643574e-003 + 0.4056436121463776 + 1 + <_> + + + + <_>7 2 4 2 -1. + <_>7 2 2 1 2. + <_>9 3 2 1 2. + 0 + 4.9113907152786851e-004 + 0.6174048185348511 + 0.4471754133701325 + <_> + + <_> + + + + <_>7 4 9 3 -1. + <_>7 5 9 1 3. + 0 + 8.2117747515439987e-003 + 1 + 0.6179698109626770 + <_> + + + + <_>10 4 5 12 -1. + <_>10 10 5 6 2. + 0 + -0.0455644801259041 + 0.2285494953393936 + 0.5249565839767456 + <_> + + <_> + + + + <_>3 12 2 3 -1. + <_>3 13 2 1 3. + 0 + -5.3631910122931004e-003 + 0.1784950047731400 + 1 + <_> + + + + <_>8 8 3 5 -1. + <_>9 8 1 5 3. + 0 + -0.0122749703004956 + 0.7261952757835388 + 0.4550398886203766 + <_> + + <_> + + + + <_>13 9 2 3 -1. + <_>13 9 1 3 2. + 0 + 5.4185991175472736e-003 + 0.5252990722656250 + 1 + <_> + + + + <_>15 11 2 2 -1. + <_>15 12 2 1 2. + 0 + 8.1846961984410882e-004 + 0.5445222258567810 + 0.3272218108177185 + <_> + + <_> + + + + <_>5 6 2 3 -1. + <_>5 7 2 1 3. + 0 + 4.1358140297234058e-003 + 1 + 0.7013831734657288 + <_> + + + + <_>2 11 6 2 -1. + <_>2 12 6 1 2. + 0 + 3.9578010910190642e-004 + 0.4965943992137909 + 0.3295598030090332 + <_> + + <_> + + + + <_>15 11 4 3 -1. + <_>15 12 4 1 3. + 0 + 4.6887691132724285e-003 + 0.5362641811370850 + 1 + <_> + + + + <_>16 0 4 17 -1. + <_>16 0 2 17 2. + 0 + -0.0182554405182600 + 0.6496108770370483 + 0.4757137000560761 + <_> + + <_> + + + + <_>1 11 4 3 -1. + <_>1 12 4 1 3. + 0 + -6.2736468389630318e-003 + 0.2343741059303284 + 1 + <_> + + + + <_>9 11 1 3 -1. + <_>9 12 1 1 3. + 0 + 2.4320168886333704e-003 + 0.4620118141174316 + 0.6898419260978699 + <_> + + <_> + + + + <_>10 9 6 7 -1. + <_>10 9 3 7 2. + 0 + -0.0496176294982433 + 0.2100719958543778 + 1 + <_> + + + + <_>8 15 4 2 -1. + <_>8 16 4 1 2. + 0 + 1.1701210169121623e-003 + 0.4621528983116150 + 0.5797135829925537 + <_> + + <_> + + + + <_>4 9 6 7 -1. + <_>7 9 3 7 2. + 0 + -0.0452372916042805 + 0.2118262052536011 + 1 + <_> + + + + <_>9 14 2 3 -1. + <_>9 15 2 1 3. + 0 + 4.7563421539962292e-003 + 0.4884614944458008 + 0.6872498989105225 + <_> + + <_> + + + + <_>0 2 20 2 -1. + <_>10 2 10 1 2. + <_>0 3 10 1 2. + 0 + -0.0148359695449471 + 1 + 0.5275105834007263 + <_> + + + + <_>6 7 8 2 -1. + <_>6 8 8 1 2. + 0 + 7.7436608262360096e-004 + 0.4172320961952210 + 0.5491139888763428 + <_> + + <_> + + + + <_>0 2 20 2 -1. + <_>0 2 10 1 2. + <_>10 3 10 1 2. + 0 + 0.0148359695449471 + 1 + 0.2124876976013184 + <_> + + + + <_>3 1 2 10 -1. + <_>3 1 1 5 2. + <_>4 6 1 5 2. + 0 + -8.0892542609944940e-004 + 0.5495215058326721 + 0.4207795858383179 + <_> + + <_> + + + + <_>13 4 1 10 -1. + <_>13 9 1 5 2. + 0 + 7.7517668250948191e-004 + 0.3321942090988159 + 1 + <_> + + + + <_>9 8 4 3 -1. + <_>9 9 4 1 3. + 0 + -6.7618978209793568e-003 + 0.2212958037853241 + 0.5232653021812439 + <_> + + <_> + + + + <_>2 11 16 4 -1. + <_>2 11 8 2 2. + <_>10 13 8 2 2. + 0 + -0.0401358604431152 + 0.1101796030998230 + 1 + <_> + + + + <_>5 1 3 5 -1. + <_>6 1 1 5 3. + 0 + -3.3651469275355339e-003 + 0.3810100853443146 + 0.5617291927337647 + <_> + + <_> + + + + <_>9 10 2 3 -1. + <_>9 11 2 1 3. + 0 + 7.4713007779791951e-004 + 1 + 0.5795056819915772 + <_> + + + + <_>9 11 2 2 -1. + <_>9 12 2 1 2. + 0 + -4.2727389372885227e-003 + 0.6392269134521484 + 0.4711438119411469 + <_> + + <_> + + + + <_>0 10 20 2 -1. + <_>0 11 20 1 2. + 0 + 3.6202510818839073e-003 + 1 + 0.3409883975982666 + <_> + + + + <_>1 7 6 4 -1. + <_>1 7 3 2 2. + <_>4 9 3 2 2. + 0 + 4.7307618660852313e-004 + 0.3659302890300751 + 0.5388171076774597 + <_> + + <_> + + + + <_>12 0 8 8 -1. + <_>16 0 4 4 2. + <_>12 4 4 4 2. + 0 + 0.0330949090421200 + 1 + 0.7170385718345642 + <_> + + + + <_>14 1 6 4 -1. + <_>16 1 2 4 3. + 0 + -0.0115441195666790 + 0.6386818289756775 + 0.4681304097175598 + <_> + + <_> + + + + <_>6 3 2 14 -1. + <_>6 10 2 7 2. + 0 + -7.4234469793736935e-003 + 0.3263700902462006 + 1 + <_> + + + + <_>6 1 7 12 -1. + <_>6 7 7 6 2. + 0 + -4.2252950370311737e-003 + 0.5767819285392761 + 0.4346418082714081 + <_> + + <_> + + + + <_>5 0 15 5 -1. + <_>10 0 5 5 3. + 0 + 0.0181331094354391 + 0.4697827994823456 + 1 + <_> + + + + <_>15 0 4 10 -1. + <_>15 0 2 10 2. + 0 + 7.0903049781918526e-003 + 0.4437389075756073 + 0.6061668992042542 + <_> + + <_> + + + + <_>1 0 18 3 -1. + <_>7 0 6 3 3. + 0 + -0.0132729401811957 + 0.6558511257171631 + 1 + <_> + + + + <_>0 0 17 2 -1. + <_>0 1 17 1 2. + 0 + 1.4632199599873275e-004 + 0.3376353979110718 + 0.5091655254364014 + <_> + + <_> + + + + <_>10 0 3 3 -1. + <_>11 0 1 3 3. + 0 + -3.5790191031992435e-003 + 0.2947883903980255 + 1 + <_> + + + + <_>10 0 3 12 -1. + <_>11 0 1 12 3. + 0 + -4.6997101162560284e-004 + 0.5556982159614563 + 0.4665456116199493 + <_> + + <_> + + + + <_>1 3 4 16 -1. + <_>1 3 2 8 2. + <_>3 11 2 8 2. + 0 + -0.0481794402003288 + 0.7338355779647827 + 1 + <_> + + + + <_>7 0 3 3 -1. + <_>8 0 1 3 3. + 0 + -9.2581362696364522e-004 + 0.3543871939182282 + 0.5285149812698364 + <_> + + <_> + + + + <_>9 13 2 6 -1. + <_>9 16 2 3 2. + 0 + -0.0147807300090790 + 0.1944441944360733 + 1 + <_> + + + + <_>9 0 6 13 -1. + <_>11 0 2 13 3. + 0 + -0.1002745032310486 + 0.0990492925047874 + 0.5139853954315186 + <_> + + <_> + + + + <_>7 7 3 2 -1. + <_>8 7 1 2 3. + 0 + -9.3848101096227765e-004 + 0.5827109813690186 + 1 + <_> + + + + <_>8 2 1 12 -1. + <_>8 6 1 4 3. + 0 + -2.8861360624432564e-003 + 0.3441427946090698 + 0.5148838758468628 + <_> + + <_> + + + + <_>4 10 12 6 -1. + <_>10 10 6 3 2. + <_>4 13 6 3 2. + 0 + -0.0436827614903450 + 1 + 0.5207998156547546 + <_> + + + + <_>13 5 2 3 -1. + <_>13 6 2 1 3. + 0 + 2.6115700602531433e-003 + 0.4835503101348877 + 0.6322219967842102 + <_> + + <_> + + + + <_>4 10 12 6 -1. + <_>4 10 6 3 2. + <_>10 13 6 3 2. + 0 + 0.0436827614903450 + 1 + 0.1364538073539734 + <_> + + + + <_>5 5 2 3 -1. + <_>5 6 2 1 3. + 0 + 1.7179530113935471e-003 + 0.4537320137023926 + 0.6066750884056091 + <_> + + <_> + + + + <_>8 6 6 7 -1. + <_>10 6 2 7 3. + 0 + -0.0339649096131325 + 1 + 0.4968374967575073 + <_> + + + + <_>9 6 2 4 -1. + <_>9 6 1 4 2. + 0 + -1.0993590112775564e-003 + 0.5831680893898010 + 0.4688239991664887 + <_> + + <_> + + + + <_>6 6 6 7 -1. + <_>8 6 2 7 3. + 0 + 0.0543010793626308 + 1 + 0.7568289041519165 + <_> + + + + <_>9 6 2 4 -1. + <_>10 6 1 4 2. + 0 + 1.0993590112775564e-003 + 0.4330148100852966 + 0.5768468976020813 + <_> + + <_> + + + + <_>12 9 2 3 -1. + <_>12 9 1 3 2. + 0 + -1.4954120160837192e-005 + 1 + 0.4443281888961792 + <_> + + + + <_>0 6 20 1 -1. + <_>0 6 10 1 2. + 0 + 0.0314158685505390 + 0.5274472832679749 + 0.3037855923175812 + <_> + + <_> + + + + <_>5 7 10 2 -1. + <_>10 7 5 2 2. + 0 + 0.0108318496495485 + 1 + 0.3581720888614655 + <_> + + + + <_>1 16 4 3 -1. + <_>1 17 4 1 3. + 0 + 8.6545711383223534e-004 + 0.5937584042549133 + 0.4294629991054535 + <_> + + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + 2.2743160370737314e-003 + 1 + 0.5954576730728149 + <_> + + + + <_>10 3 5 3 -1. + <_>10 4 5 1 3. + 0 + 3.9340821094810963e-003 + 0.4792222976684570 + 0.5856133103370667 + <_> + + <_> + + + + <_>3 9 14 8 -1. + <_>3 9 7 4 2. + <_>10 13 7 4 2. + 0 + 8.1451907753944397e-003 + 1 + 0.3573477864265442 + <_> + + + + <_>6 8 8 10 -1. + <_>6 8 4 5 2. + <_>10 13 4 5 2. + 0 + -5.2763288840651512e-003 + 0.4026022851467133 + 0.5764743089675903 + <_> + + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + -8.3787851035594940e-003 + 1 + 0.4981333017349243 + <_> + + + + <_>10 3 5 3 -1. + <_>10 4 5 1 3. + 0 + 1.5621910570189357e-003 + 0.4736588001251221 + 0.5583608150482178 + <_> + + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + 3.2318739686161280e-003 + 1 + 0.6167436838150024 + <_> + + + + <_>5 3 5 3 -1. + <_>5 4 5 1 3. + 0 + 6.6804019734263420e-003 + 0.4131424129009247 + 0.6280695199966431 + <_> + + <_> + + + + <_>13 16 2 3 -1. + <_>13 17 2 1 3. + 0 + -3.3396480139344931e-003 + 0.3446358144283295 + 1 + <_> + + + + <_>0 5 20 6 -1. + <_>0 7 20 2 3. + 0 + -0.2093348056077957 + 0.1038658022880554 + 0.5204489231109619 + <_> + + <_> + + + + <_>3 14 3 3 -1. + <_>3 15 3 1 3. + 0 + 6.3805822283029556e-003 + 1 + 0.2167402058839798 + <_> + + + + <_>7 15 5 3 -1. + <_>7 16 5 1 3. + 0 + -6.0137799009680748e-003 + 0.6738399267196655 + 0.4896650910377502 + <_> + + <_> + + + + <_>12 9 2 3 -1. + <_>12 9 1 3 2. + 0 + -8.1756077706813812e-003 + 1 + 0.5177915096282959 + <_> + + + + <_>15 13 2 6 -1. + <_>15 13 1 6 2. + 0 + 6.3951779156923294e-004 + 0.4819645881652832 + 0.5464438199996948 + <_> + + <_> + + + + <_>6 9 2 3 -1. + <_>7 9 1 3 2. + 0 + 1.0127760469913483e-003 + 1 + 0.3423596024513245 + <_> + + + + <_>3 13 2 6 -1. + <_>4 13 1 6 2. + 0 + 4.9784599104896188e-004 + 0.4488461017608643 + 0.5912671089172363 + <_> + + <_> + + + + <_>11 4 2 4 -1. + <_>11 4 1 4 2. + 0 + 1.3596490316558629e-004 + 1 + 0.5568863153457642 + <_> + + + + <_>13 4 2 5 -1. + <_>13 4 1 5 2. + 0 + 0.0135716600343585 + 0.5161067843437195 + 0.1713000982999802 + <_> + + <_> + + + + <_>7 4 2 4 -1. + <_>8 4 1 4 2. + 0 + 3.0259079721872695e-005 + 1 + 0.4916203916072846 + <_> + + + + <_>5 4 2 5 -1. + <_>6 4 1 5 2. + 0 + -3.2625840976834297e-003 + 0.6404662728309631 + 0.2859084904193878 + <_> + + <_> + + + + <_>19 6 1 2 -1. + <_>19 7 1 1 2. + 0 + -1.9217010412830859e-004 + 1 + 0.5459282994270325 + <_> + + + + <_>12 7 8 13 -1. + <_>12 7 4 13 2. + 0 + 0.0219938792288303 + 0.4715713858604431 + 0.5690075159072876 + <_> + + <_> + + + + <_>0 6 1 2 -1. + <_>0 7 1 1 2. + 0 + 7.8907777788117528e-004 + 1 + 0.3279826939105988 + <_> + + + + <_>6 15 4 3 -1. + <_>6 16 4 1 3. + 0 + 5.0893891602754593e-004 + 0.4302007853984833 + 0.5696045160293579 + <_> + + <_> + + + + <_>11 8 2 2 -1. + <_>11 9 2 1 2. + 0 + 1.1662710312521085e-004 + 1 + 0.5387235283851624 + <_> + + + + <_>11 7 2 4 -1. + <_>11 7 1 4 2. + 0 + 8.0604078248143196e-003 + 0.5021423101425171 + 0.5965322256088257 + <_> + + <_> + + + + <_>4 13 2 3 -1. + <_>4 14 2 1 3. + 0 + 9.5925969071686268e-004 + 1 + 0.3473494052886963 + <_> + + + + <_>0 17 18 3 -1. + <_>6 17 6 3 3. + 0 + -0.0195261295884848 + 0.6475545167922974 + 0.4643782079219818 + 36.7265014648437500 + 13 + -1 + <_> + + + <_> + + <_> + + + + <_>1 0 18 5 -1. + <_>7 0 6 5 3. + 0 + 0.0412424392998219 + 0.3393315076828003 + 1 + <_> + + + + <_>5 7 3 4 -1. + <_>5 9 3 2 2. + 0 + 0.0156267099082470 + 0.5104100108146668 + 0.7772815227508545 + <_> + + <_> + + + + <_>10 6 2 2 -1. + <_>10 6 1 2 2. + 0 + 2.9947189614176750e-004 + 0.3664673864841461 + 1 + <_> + + + + <_>6 4 14 4 -1. + <_>13 4 7 2 2. + <_>6 6 7 2 2. + 0 + -1.0037609608843923e-003 + 0.5405650734901428 + 0.3926205039024353 + <_> + + <_> + + + + <_>5 16 6 4 -1. + <_>5 16 3 2 2. + <_>8 18 3 2 2. + 0 + 6.8128242855891585e-004 + 0.4251519143581390 + 1 + <_> + + + + <_>7 15 2 4 -1. + <_>7 17 2 2 2. + 0 + 1.3098999625071883e-004 + 0.4135144948959351 + 0.6925746202468872 + <_> + + <_> + + + + <_>8 5 5 14 -1. + <_>8 12 5 7 2. + 0 + 3.1696720980107784e-003 + 1 + 0.3455873131752014 + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + -2.0587369799613953e-003 + 0.2234193980693817 + 0.5286118984222412 + <_> + + <_> + + + + <_>7 5 3 7 -1. + <_>8 5 1 7 3. + 0 + -4.6395038953050971e-004 + 1 + 0.4206520020961762 + <_> + + + + <_>0 0 3 9 -1. + <_>0 3 3 3 3. + 0 + 3.5089480224996805e-003 + 0.6502981781959534 + 0.4117597937583923 + <_> + + <_> + + + + <_>8 6 8 8 -1. + <_>12 6 4 4 2. + <_>8 10 4 4 2. + 0 + -2.3975980002433062e-003 + 1 + 0.3673301041126251 + <_> + + + + <_>4 8 13 2 -1. + <_>4 9 13 1 2. + 0 + 1.0901279747486115e-003 + 0.2906238138675690 + 0.5445111989974976 + <_> + + <_> + + + + <_>4 3 6 1 -1. + <_>6 3 2 1 3. + 0 + -1.6524370585102588e-004 + 0.4233515858650208 + 1 + <_> + + + + <_>9 1 2 6 -1. + <_>9 3 2 2 3. + 0 + -4.1602319106459618e-004 + 0.3886361122131348 + 0.6269165873527527 + <_> + + <_> + + + + <_>10 5 6 4 -1. + <_>12 5 2 4 3. + 0 + -2.3739910102449358e-004 + 0.5524451136589050 + 1 + <_> + + + + <_>9 5 2 12 -1. + <_>9 9 2 4 3. + 0 + 0.0247397609055042 + 0.4960095882415772 + 0.5373491048812866 + <_> + + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + -0.0153428399935365 + 0.6849405169487000 + 1 + <_> + + + + <_>8 12 4 3 -1. + <_>8 13 4 1 3. + 0 + 0.0115404697135091 + 0.4037235081195831 + 0.6786940097808838 + <_> + + <_> + + + + <_>10 3 6 7 -1. + <_>12 3 2 7 3. + 0 + 6.4230621792376041e-003 + 1 + 0.3814676105976105 + <_> + + + + <_>3 10 16 6 -1. + <_>3 12 16 2 3. + 0 + 0.0129778096452355 + 0.5527058839797974 + 0.3744955956935883 + <_> + + <_> + + + + <_>5 5 3 10 -1. + <_>5 10 3 5 2. + 0 + 1.1063399724662304e-003 + 0.3520928919315338 + 1 + <_> + + + + <_>6 10 3 6 -1. + <_>6 13 3 3 2. + 0 + 1.3743690215051174e-003 + 0.5641903281211853 + 0.3075025975704193 + <_> + + <_> + + + + <_>17 2 2 12 -1. + <_>17 2 1 12 2. + 0 + 0.0162337794899940 + 0.4888828098773956 + 1 + <_> + + + + <_>16 6 2 14 -1. + <_>16 13 2 7 2. + 0 + -8.1519351806491613e-004 + 0.5456321239471436 + 0.4743550121784210 + <_> + + <_> + + + + <_>3 11 12 9 -1. + <_>3 14 12 3 3. + 0 + -0.0907824933528900 + 0.2925248146057129 + 1 + <_> + + + + <_>0 2 4 12 -1. + <_>2 2 2 12 2. + 0 + 0.0116652101278305 + 0.4688454866409302 + 0.6230347752571106 + <_> + + <_> + + + + <_>18 0 2 18 -1. + <_>18 0 1 18 2. + 0 + -0.0232864096760750 + 0.6895843148231506 + 1 + <_> + + + + <_>16 12 3 2 -1. + <_>16 13 3 1 2. + 0 + 2.1559339947998524e-003 + 0.5355802178382874 + 0.3423466086387634 + <_> + + <_> + + + + <_>0 2 2 15 -1. + <_>1 2 1 15 2. + 0 + -4.3167220428586006e-003 + 0.5937076210975647 + 1 + <_> + + + + <_>1 10 2 4 -1. + <_>1 12 2 2 2. + 0 + 1.5610599657520652e-003 + 0.4708659946918488 + 0.2736997008323669 + <_> + + <_> + + + + <_>11 1 2 18 -1. + <_>11 1 1 18 2. + 0 + 0.0140766398981214 + 0.5287156105041504 + 1 + <_> + + + + <_>3 2 14 2 -1. + <_>10 2 7 1 2. + <_>3 3 7 1 2. + 0 + 7.1018589660525322e-003 + 0.5336192846298218 + 0.3224813938140869 + <_> + + <_> + + + + <_>7 1 2 18 -1. + <_>8 1 1 18 2. + 0 + -4.8221647739410400e-003 + 0.2983910143375397 + 1 + <_> + + + + <_>6 1 8 12 -1. + <_>6 7 8 6 2. + 0 + -5.3852899000048637e-003 + 0.5623999238014221 + 0.4295912086963654 + <_> + + <_> + + + + <_>8 14 4 3 -1. + <_>8 15 4 1 3. + 0 + 7.3483278974890709e-003 + 1 + 0.6813961267471314 + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + -3.5707519855350256e-003 + 0.5857968926429749 + 0.4603429138660431 + <_> + + <_> + + + + <_>0 13 5 2 -1. + <_>0 14 5 1 2. + 0 + 2.3340100888162851e-003 + 1 + 0.2744851112365723 + <_> + + + + <_>9 0 2 6 -1. + <_>9 0 1 3 2. + <_>10 3 1 3 2. + 0 + 4.7432780265808105e-003 + 0.5047526955604553 + 0.2362741976976395 + <_> + + <_> + + + + <_>9 0 2 6 -1. + <_>10 0 1 3 2. + <_>9 3 1 3 2. + 0 + 6.5055489540100098e-003 + 0.5242248177528381 + 1 + <_> + + + + <_>9 7 3 6 -1. + <_>10 7 1 6 3. + 0 + 0.0125892497599125 + 0.4823690950870514 + 0.6752536892890930 + <_> + + <_> + + + + <_>9 0 2 6 -1. + <_>9 0 1 3 2. + <_>10 3 1 3 2. + 0 + -6.3358368352055550e-003 + 0.1734634935855866 + 1 + <_> + + + + <_>8 7 3 6 -1. + <_>9 7 1 6 3. + 0 + -5.7639651931822300e-003 + 0.6354380846023560 + 0.4587475061416626 + <_> + + <_> + + + + <_>9 6 2 6 -1. + <_>9 6 1 6 2. + 0 + 1.3599749654531479e-003 + 0.4580380916595459 + 1 + <_> + + + + <_>9 4 4 3 -1. + <_>9 4 2 3 2. + 0 + 0.0284042600542307 + 0.5176380872726440 + 0.1204385012388229 + <_> + + <_> + + + + <_>0 4 4 3 -1. + <_>0 5 4 1 3. + 0 + -9.2958156019449234e-003 + 0.2337957024574280 + 1 + <_> + + + + <_>8 7 4 2 -1. + <_>8 8 4 1 2. + 0 + -1.1800320353358984e-003 + 0.3902814090251923 + 0.5652930140495300 + <_> + + <_> + + + + <_>10 6 6 3 -1. + <_>12 6 2 3 3. + 0 + -2.0948140881955624e-003 + 0.5512028932571411 + 1 + <_> + + + + <_>9 6 3 12 -1. + <_>9 10 3 4 3. + 0 + 4.1679958812892437e-003 + 0.5455976128578186 + 0.4798949062824249 + <_> + + <_> + + + + <_>5 4 2 3 -1. + <_>5 5 2 1 3. + 0 + 5.4458891972899437e-003 + 1 + 0.6127086877822876 + <_> + + + + <_>5 6 1 3 -1. + <_>5 7 1 1 3. + 0 + -1.2766510481014848e-003 + 0.5317131876945496 + 0.3850932121276856 + <_> + + <_> + + + + <_>9 17 3 2 -1. + <_>10 17 1 2 3. + 0 + 5.9404270723462105e-004 + 0.5446437001228333 + 1 + <_> + + + + <_>0 7 20 2 -1. + <_>0 8 20 1 2. + 0 + 0.0423096083104610 + 0.5234643816947937 + 0.2213044017553330 + <_> + + <_> + + + + <_>4 3 6 7 -1. + <_>6 3 2 7 3. + 0 + 5.6189671158790588e-003 + 0.4916197955608368 + 1 + <_> + + + + <_>5 10 6 10 -1. + <_>5 10 3 5 2. + <_>8 15 3 5 2. + 0 + 7.2401198558509350e-003 + 0.1471475958824158 + 0.4852893948554993 + <_> + + <_> + + + + <_>9 17 3 2 -1. + <_>10 17 1 2 3. + 0 + -4.5610670931637287e-003 + 0.2773773968219757 + 1 + <_> + + + + <_>9 10 2 2 -1. + <_>9 11 2 1 2. + 0 + 4.5506159949582070e-005 + 0.4626461863517761 + 0.5768079161643982 + <_> + + <_> + + + + <_>8 17 3 2 -1. + <_>9 17 1 2 3. + 0 + -6.1903791502118111e-003 + 0.1644289940595627 + 1 + <_> + + + + <_>5 6 1 3 -1. + <_>5 7 1 1 3. + 0 + 8.1186462193727493e-004 + 0.4778591096401215 + 0.6261864900588989 + <_> + + <_> + + + + <_>0 1 20 2 -1. + <_>10 1 10 1 2. + <_>0 2 10 1 2. + 0 + 0.0137798096984625 + 0.5257307887077332 + 1 + <_> + + + + <_>14 2 6 9 -1. + <_>14 5 6 3 3. + 0 + 1.1290319962427020e-003 + 0.5498048067092896 + 0.3983106911182404 + <_> + + <_> + + + + <_>5 3 3 2 -1. + <_>5 4 3 1 2. + 0 + -1.0610350000206381e-004 + 0.4033519029617310 + 1 + <_> + + + + <_>5 4 4 2 -1. + <_>7 4 2 2 2. + 0 + 1.6695790691301227e-004 + 0.4149340093135834 + 0.5795341134071350 + <_> + + <_> + + + + <_>14 2 6 9 -1. + <_>14 5 6 3 3. + 0 + 1.1290319962427020e-003 + 1 + 0.3934114873409271 + <_> + + + + <_>0 12 20 6 -1. + <_>0 14 20 2 3. + 0 + -0.1201934963464737 + 0.0734004825353622 + 0.5202586054801941 + <_> + + <_> + + + + <_>2 2 16 4 -1. + <_>2 2 8 2 2. + <_>10 4 8 2 2. + 0 + -0.0152307404205203 + 0.3749505877494812 + 1 + <_> + + + + <_>7 12 5 3 -1. + <_>7 13 5 1 3. + 0 + 3.5759829916059971e-003 + 0.5078150033950806 + 0.6606066226959229 + <_> + + <_> + + + + <_>14 9 6 10 -1. + <_>14 9 3 10 2. + 0 + 0.0134794600307941 + 0.4547711014747620 + 1 + <_> + + + + <_>16 6 3 2 -1. + <_>16 7 3 1 2. + 0 + -2.1162950433790684e-003 + 0.3311006128787994 + 0.5384259223937988 + <_> + + <_> + + + + <_>0 9 6 10 -1. + <_>3 9 3 10 2. + 0 + -0.0178777091205120 + 0.6513252854347229 + 1 + <_> + + + + <_>0 16 5 2 -1. + <_>0 17 5 1 2. + 0 + 1.0931970318779349e-003 + 0.5264765024185181 + 0.3456991016864777 + <_> + + <_> + + + + <_>9 12 2 3 -1. + <_>9 13 2 1 3. + 0 + -3.0553159303963184e-003 + 0.6268613934516907 + 1 + <_> + + + + <_>9 7 2 12 -1. + <_>9 11 2 4 3. + 0 + 3.6365049891173840e-003 + 0.5399212837219238 + 0.4345397055149078 + <_> + + <_> + + + + <_>3 2 6 2 -1. + <_>5 2 2 2 3. + 0 + 9.7896481747739017e-005 + 0.3835605978965759 + 1 + <_> + + + + <_>4 1 1 2 -1. + <_>4 2 1 1 2. + 0 + -3.2714448752813041e-004 + 0.3337667882442474 + 0.5539165735244751 + <_> + + <_> + + + + <_>11 15 1 2 -1. + <_>11 16 1 1 2. + 0 + 4.3425030889920890e-004 + 1 + 0.5788270235061646 + <_> + + + + <_>3 1 16 2 -1. + <_>11 1 8 1 2. + <_>3 2 8 1 2. + 0 + 0.0140055799856782 + 0.5275077819824219 + 0.2701125144958496 + <_> + + <_> + + + + <_>3 6 2 2 -1. + <_>3 6 1 1 2. + <_>4 7 1 1 2. + 0 + -9.2654931358993053e-004 + 0.5852280259132385 + 1 + <_> + + + + <_>5 11 10 6 -1. + <_>5 11 5 3 2. + <_>10 14 5 3 2. + 0 + 3.9504268206655979e-003 + 0.4728336930274963 + 0.3313918113708496 + <_> + + <_> + + + + <_>10 11 4 6 -1. + <_>10 14 4 3 2. + 0 + -5.8086868375539780e-004 + 1 + 0.4258810877799988 + <_> + + + + <_>14 9 6 11 -1. + <_>16 9 2 11 3. + 0 + -0.0120180202648044 + 0.5609787106513977 + 0.4895192086696625 + <_> + + <_> + + + + <_>0 9 6 11 -1. + <_>2 9 2 11 3. + 0 + -0.1452154070138931 + 0.0438944809138775 + 1 + <_> + + + + <_>2 11 16 6 -1. + <_>2 11 8 3 2. + <_>10 14 8 3 2. + 0 + -6.6049019806087017e-003 + 0.4229170978069305 + 0.5616292953491211 + <_> + + <_> + + + + <_>12 0 8 10 -1. + <_>16 0 4 5 2. + <_>12 5 4 5 2. + 0 + -0.0349097512662411 + 1 + 0.4788128137588501 + <_> + + + + <_>14 2 6 4 -1. + <_>16 2 2 4 3. + 0 + 3.7478420417755842e-003 + 0.4800282120704651 + 0.5801389217376709 + <_> + + <_> + + + + <_>0 0 8 10 -1. + <_>0 0 4 5 2. + <_>4 5 4 5 2. + 0 + 0.0330380313098431 + 1 + 0.7078176140785217 + <_> + + + + <_>0 2 6 4 -1. + <_>2 2 2 4 3. + 0 + 3.6872599739581347e-003 + 0.4449624121189117 + 0.5957731008529663 + <_> + + <_> + + + + <_>4 9 15 2 -1. + <_>9 9 5 2 3. + 0 + -4.5311939902603626e-003 + 0.4177047014236450 + 1 + <_> + + + + <_>12 3 4 8 -1. + <_>14 3 2 4 2. + <_>12 7 2 4 2. + 0 + 4.1058510541915894e-003 + 0.5372948050498962 + 0.3736926913261414 + <_> + + <_> + + + + <_>9 2 2 9 -1. + <_>10 2 1 9 2. + 0 + -8.7599847465753555e-003 + 0.6658807992935181 + 1 + <_> + + + + <_>0 2 20 1 -1. + <_>10 2 10 1 2. + 0 + -0.0230033099651337 + 0.2647922039031982 + 0.5101817846298218 + <_> + + <_> + + + + <_>16 1 4 5 -1. + <_>16 1 2 5 2. + 0 + 5.3664818406105042e-003 + 0.4548634886741638 + 1 + <_> + + + + <_>16 0 4 6 -1. + <_>16 3 4 3 2. + 0 + 0.0389717705547810 + 0.5157061815261841 + 0.3436439037322998 + <_> + + <_> + + + + <_>4 3 6 4 -1. + <_>6 3 2 4 3. + 0 + -0.0277671907097101 + 0.2354391068220139 + 1 + <_> + + + + <_>0 0 18 5 -1. + <_>6 0 6 5 3. + 0 + -9.8894089460372925e-003 + 0.6887741088867188 + 0.5111051797866821 + <_> + + <_> + + + + <_>6 2 12 14 -1. + <_>12 2 6 7 2. + <_>6 9 6 7 2. + 0 + -3.2073140610009432e-003 + 0.5438867807388306 + 1 + <_> + + + + <_>11 8 3 5 -1. + <_>12 8 1 5 3. + 0 + -6.7484978353604674e-004 + 0.5451148748397827 + 0.4831353127956390 + <_> + + <_> + + + + <_>5 12 2 2 -1. + <_>5 13 2 1 2. + 0 + -5.1947520114481449e-003 + 0.2113419026136398 + 1 + <_> + + + + <_>5 10 4 3 -1. + <_>7 10 2 3 2. + 0 + -2.6169899501837790e-004 + 0.5273681879043579 + 0.3992587029933929 + <_> + + <_> + + + + <_>4 9 15 2 -1. + <_>9 9 5 2 3. + 0 + 2.2421479225158691e-003 + 0.4688260853290558 + 1 + <_> + + + + <_>10 7 6 2 -1. + <_>12 7 2 2 3. + 0 + -1.2139769969508052e-003 + 0.5504235029220581 + 0.4384871125221252 + <_> + + <_> + + + + <_>1 9 15 2 -1. + <_>6 9 5 2 3. + 0 + -2.9469770379364491e-003 + 0.3892847001552582 + 1 + <_> + + + + <_>5 0 2 10 -1. + <_>5 0 1 5 2. + <_>6 5 1 5 2. + 0 + -3.9291830034926534e-004 + 0.6001722812652588 + 0.4561662971973419 + <_> + + <_> + + + + <_>0 0 20 14 -1. + <_>0 7 20 7 2. + 0 + 0.6255072951316834 + 1 + 0.0681256130337715 + <_> + + + + <_>12 7 8 4 -1. + <_>12 7 4 4 2. + 0 + 9.7744520753622055e-003 + 0.4813025891780853 + 0.5620657205581665 + <_> + + <_> + + + + <_>0 7 8 4 -1. + <_>4 7 4 4 2. + 0 + 0.0943782478570938 + 1 + 0.0666322931647301 + <_> + + + + <_>8 1 3 3 -1. + <_>9 1 1 3 3. + 0 + -1.9560910295695066e-003 + 0.3588232994079590 + 0.5295407176017761 + <_> + + <_> + + + + <_>9 7 3 4 -1. + <_>10 7 1 4 3. + 0 + 9.0652769431471825e-003 + 0.4822688102722168 + 1 + <_> + + + + <_>9 9 3 1 -1. + <_>10 9 1 1 3. + 0 + 4.2138071148656309e-004 + 0.4670332968235016 + 0.5683112740516663 + <_> + + <_> + + + + <_>8 9 3 2 -1. + <_>8 10 3 1 2. + 0 + -4.4220191193744540e-004 + 1 + 0.5360795259475708 + <_> + + + + <_>8 4 2 8 -1. + <_>8 4 1 4 2. + <_>9 8 1 4 2. + 0 + -4.7313501127064228e-003 + 0.6137245893478394 + 0.3188089132308960 + <_> + + <_> + + + + <_>5 8 12 3 -1. + <_>5 9 12 1 3. + 0 + 1.5395509544759989e-003 + 0.4487720131874085 + 1 + <_> + + + + <_>11 14 1 3 -1. + <_>11 15 1 1 3. + 0 + 2.4315000046044588e-003 + 0.4894166886806488 + 0.6716653704643250 + <_> + + <_> + + + + <_>6 10 3 6 -1. + <_>6 12 3 2 3. + 0 + -0.0155816199257970 + 0.3336741924285889 + 1 + <_> + + + + <_>4 17 8 3 -1. + <_>4 18 8 1 3. + 0 + 1.0816920548677444e-003 + 0.4718219935894013 + 0.5960627198219299 + <_> + + <_> + + + + <_>17 6 2 3 -1. + <_>17 7 2 1 3. + 0 + -2.2197659127414227e-003 + 0.3588554859161377 + 1 + <_> + + + + <_>9 12 2 2 -1. + <_>10 12 1 1 2. + <_>9 13 1 1 2. + 0 + -9.3048671260476112e-004 + 0.6218712925910950 + 0.4817300140857697 + <_> + + <_> + + + + <_>9 13 2 4 -1. + <_>9 13 1 2 2. + <_>10 15 1 2 2. + 0 + -4.7418707981705666e-003 + 0.2550027072429657 + 1 + <_> + + + + <_>9 11 2 3 -1. + <_>9 12 2 1 3. + 0 + -6.2950369901955128e-003 + 0.6728078722953796 + 0.5051063895225525 + <_> + + <_> + + + + <_>5 5 12 10 -1. + <_>11 5 6 5 2. + <_>5 10 6 5 2. + 0 + 3.5216049291193485e-003 + 0.5401909947395325 + 1 + <_> + + + + <_>6 3 12 12 -1. + <_>12 3 6 6 2. + <_>6 9 6 6 2. + 0 + -2.4289379362016916e-003 + 0.5419461727142334 + 0.4347142875194550 + <_> + + <_> + + + + <_>5 7 2 2 -1. + <_>5 7 1 1 2. + <_>6 8 1 1 2. + 0 + -2.5261470582336187e-003 + 0.6970624923706055 + 1 + <_> + + + + <_>4 3 3 2 -1. + <_>5 3 1 2 3. + 0 + -1.4817339833825827e-003 + 0.3263416886329651 + 0.4917873144149780 + <_> + + <_> + + + + <_>6 2 12 14 -1. + <_>12 2 6 7 2. + <_>6 9 6 7 2. + 0 + -0.2247453033924103 + 7.2937291115522385e-003 + 1 + <_> + + + + <_>5 2 12 3 -1. + <_>9 2 4 3 3. + 0 + 2.8342509176582098e-003 + 0.4579229950904846 + 0.5379881262779236 + <_> + + <_> + + + + <_>1 1 18 17 -1. + <_>7 1 6 17 3. + 0 + -0.0208216104656458 + 0.6024088859558106 + 1 + <_> + + + + <_>0 9 10 1 -1. + <_>5 9 5 1 2. + 0 + 1.4896340144332498e-004 + 0.3336144089698792 + 0.4962815940380096 + <_> + + <_> + + + + <_>16 8 4 3 -1. + <_>16 9 4 1 3. + 0 + -3.3524499740451574e-003 + 0.3558751046657562 + 1 + <_> + + + + <_>7 13 6 6 -1. + <_>7 16 6 3 2. + 0 + -0.0372798815369606 + 0.1698562949895859 + 0.5208985805511475 + <_> + + <_> + + + + <_>6 14 1 6 -1. + <_>6 16 1 2 3. + 0 + 1.3896770542487502e-004 + 1 + 0.5590686202049255 + <_> + + + + <_>6 17 4 2 -1. + <_>6 18 4 1 2. + 0 + -3.1912620761431754e-004 + 0.5848733782768250 + 0.3795836865901947 + <_> + + <_> + + + + <_>10 18 6 2 -1. + <_>13 18 3 1 2. + <_>10 19 3 1 2. + 0 + 5.4003461264073849e-004 + 1 + 0.5670288205146790 + <_> + + + + <_>16 8 1 3 -1. + <_>16 9 1 1 3. + 0 + 3.8956850767135620e-003 + 0.5182694792747498 + 0.3327709138393402 + <_> + + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 1.6084529925137758e-003 + 1 + 0.5410485863685608 + <_> + + + + <_>9 15 1 2 -1. + <_>9 16 1 1 2. + 0 + -5.7474587811157107e-004 + 0.6022642254829407 + 0.3644644021987915 + <_> + + <_> + + + + <_>13 0 3 12 -1. + <_>14 0 1 12 3. + 0 + 0.0134350396692753 + 1 + 0.3441281914710999 + <_> + + + + <_>15 11 1 3 -1. + <_>15 12 1 1 3. + 0 + 2.1368139423429966e-003 + 0.5292434096336365 + 0.2747075855731964 + <_> + + <_> + + + + <_>8 15 3 3 -1. + <_>8 16 3 1 3. + 0 + 0.0141576295718551 + 1 + 0.8027868270874023 + <_> + + + + <_>4 0 3 12 -1. + <_>5 0 1 12 3. + 0 + 5.3884391672909260e-003 + 0.5222315192222595 + 0.3586727976799011 + <_> + + <_> + + + + <_>9 7 3 3 -1. + <_>10 7 1 3 3. + 0 + 8.8013410568237305e-003 + 0.4900386929512024 + 1 + <_> + + + + <_>9 9 3 1 -1. + <_>10 9 1 1 3. + 0 + 3.8858849438838661e-004 + 0.4681056141853333 + 0.5721952915191650 + <_> + + <_> + + + + <_>2 2 12 14 -1. + <_>2 2 6 7 2. + <_>8 9 6 7 2. + 0 + -2.2143588867038488e-003 + 0.5388805866241455 + 1 + <_> + + + + <_>4 2 12 3 -1. + <_>8 2 4 3 3. + 0 + -8.4642972797155380e-003 + 0.6675537824630737 + 0.3448441922664642 + <_> + + <_> + + + + <_>18 18 2 2 -1. + <_>18 18 1 2 2. + 0 + 0.0150443902239203 + 1 + 0.9239614009857178 + <_> + + + + <_>17 2 3 8 -1. + <_>18 2 1 8 3. + 0 + 7.6346402056515217e-003 + 0.4884896874427795 + 0.6306052803993225 + <_> + + <_> + + + + <_>0 18 2 2 -1. + <_>1 18 1 2 2. + 0 + 3.3895121305249631e-004 + 1 + 0.3997431099414825 + <_> + + + + <_>6 11 2 6 -1. + <_>6 14 2 3 2. + 0 + 2.1157610171940178e-004 + 0.5663982033729553 + 0.3972980976104736 + <_> + + <_> + + + + <_>13 10 5 6 -1. + <_>13 12 5 2 3. + 0 + -0.0275149494409561 + 1 + 0.5201063752174377 + <_> + + + + <_>5 8 15 3 -1. + <_>5 9 15 1 3. + 0 + 0.0516030602157116 + 0.5140730142593384 + 0.1245130971074104 + <_> + + <_> + + + + <_>2 10 5 6 -1. + <_>2 12 5 2 3. + 0 + 3.7510651163756847e-003 + 1 + 0.3802095055580139 + <_> + + + + <_>0 8 15 3 -1. + <_>0 9 15 1 3. + 0 + -2.1457639522850513e-003 + 0.3309448063373566 + 0.5474538803100586 + <_> + + <_> + + + + <_>16 2 3 1 -1. + <_>17 2 1 1 3. + 0 + -5.8178009930998087e-004 + 1 + 0.4892601966857910 + <_> + + + + <_>17 4 3 2 -1. + <_>18 4 1 2 3. + 0 + -9.3638541875407100e-004 + 0.5937399268150330 + 0.4664669036865234 + <_> + + <_> + + + + <_>0 8 8 12 -1. + <_>0 8 4 6 2. + <_>4 14 4 6 2. + 0 + 0.0416674911975861 + 1 + 0.7021353244781494 + <_> + + + + <_>1 7 8 6 -1. + <_>1 7 4 3 2. + <_>5 10 4 3 2. + 0 + -6.7763780243694782e-003 + 0.3222751021385193 + 0.5068395137786865 + <_> + + <_> + + + + <_>14 1 6 2 -1. + <_>16 1 2 2 3. + 0 + -2.9170580673962831e-003 + 1 + 0.4717701077461243 + <_> + + + + <_>15 0 4 4 -1. + <_>17 0 2 2 2. + <_>15 2 2 2 2. + 0 + 3.2789530814625323e-004 + 0.4509383141994476 + 0.5651162862777710 + 38.2360382080078130 + 14 + -1 + <_> + + + <_> + + <_> + + + + <_>1 1 4 11 -1. + <_>3 1 2 11 2. + 0 + 0.0117298001423478 + 0.3805224895477295 + 1 + <_> + + + + <_>5 5 1 8 -1. + <_>5 9 1 4 2. + 0 + 1.1712179984897375e-003 + 0.3140017986297607 + 0.6858146190643311 + <_> + + <_> + + + + <_>7 7 6 1 -1. + <_>9 7 2 1 3. + 0 + 9.3555096536874771e-003 + 1 + 0.6834673285484314 + <_> + + + + <_>4 7 12 2 -1. + <_>8 7 4 2 3. + 0 + 1.6570610459893942e-003 + 0.2992472946643829 + 0.5475677847862244 + <_> + + <_> + + + + <_>8 4 4 4 -1. + <_>8 6 4 2 2. + 0 + -1.3387809740379453e-003 + 1 + 0.2941406965255737 + <_> + + + + <_>2 4 9 1 -1. + <_>5 4 3 1 3. + 0 + 1.7580550047568977e-004 + 0.3896977901458740 + 0.5872970819473267 + <_> + + <_> + + + + <_>9 12 2 8 -1. + <_>9 16 2 4 2. + 0 + -2.9473248869180679e-003 + 0.3576571941375732 + 1 + <_> + + + + <_>3 8 14 12 -1. + <_>3 14 14 6 2. + 0 + 8.3220899105072021e-003 + 0.5232400894165039 + 0.3231087923049927 + <_> + + <_> + + + + <_>6 13 7 3 -1. + <_>6 14 7 1 3. + 0 + 7.4366689659655094e-003 + 1 + 0.6715673208236694 + <_> + + + + <_>5 9 6 3 -1. + <_>7 9 2 3 3. + 0 + -2.1322889369912446e-004 + 0.5470541715621948 + 0.3863396048545837 + <_> + + <_> + + + + <_>12 1 6 3 -1. + <_>12 2 6 1 3. + 0 + -7.8024631366133690e-003 + 0.2771460115909576 + 1 + <_> + + + + <_>8 12 6 2 -1. + <_>8 13 6 1 2. + 0 + 5.6611228501424193e-004 + 0.4689136147499085 + 0.5851963758468628 + <_> + + <_> + + + + <_>0 2 18 2 -1. + <_>0 2 9 1 2. + <_>9 3 9 1 2. + 0 + -9.2346500605344772e-003 + 0.2704397141933441 + 1 + <_> + + + + <_>6 10 3 6 -1. + <_>6 13 3 3 2. + 0 + -1.4676499631605111e-005 + 0.5622550249099731 + 0.3579317033290863 + <_> + + <_> + + + + <_>14 0 6 6 -1. + <_>14 0 3 6 2. + 0 + 9.7007937729358673e-003 + 0.4173871874809265 + 1 + <_> + + + + <_>15 0 5 8 -1. + <_>15 4 5 4 2. + 0 + -3.5320650786161423e-003 + 0.4195013046264648 + 0.5549468994140625 + <_> + + <_> + + + + <_>7 16 6 4 -1. + <_>9 16 2 4 3. + 0 + 0.0216164104640484 + 1 + 0.2857390940189362 + <_> + + + + <_>2 11 14 4 -1. + <_>2 11 7 2 2. + <_>9 13 7 2 2. + 0 + 3.4567608963698149e-003 + 0.6024532914161682 + 0.4377507865428925 + <_> + + <_> + + + + <_>14 10 6 10 -1. + <_>14 10 3 10 2. + 0 + 0.0229143202304840 + 0.4689350128173828 + 1 + <_> + + + + <_>9 8 10 12 -1. + <_>14 8 5 6 2. + <_>9 14 5 6 2. + 0 + 3.4328910987824202e-003 + 0.4664604961872101 + 0.5762562155723572 + <_> + + <_> + + + + <_>0 10 6 10 -1. + <_>3 10 3 10 2. + 0 + -8.6510833352804184e-003 + 0.6381739974021912 + 1 + <_> + + + + <_>1 8 10 12 -1. + <_>1 8 5 6 2. + <_>6 14 5 6 2. + 0 + 1.4510039472952485e-003 + 0.3711487948894501 + 0.5530750751495361 + <_> + + <_> + + + + <_>9 3 6 1 -1. + <_>11 3 2 1 3. + 0 + 7.8191719949245453e-003 + 0.5264362096786499 + 1 + <_> + + + + <_>7 4 6 3 -1. + <_>9 4 2 3 3. + 0 + 2.0798550394829363e-004 + 0.3730512857437134 + 0.5445731282234192 + <_> + + <_> + + + + <_>5 3 6 1 -1. + <_>7 3 2 1 3. + 0 + -3.9962218143045902e-003 + 0.2438170015811920 + 1 + <_> + + + + <_>4 5 6 3 -1. + <_>6 5 2 3 3. + 0 + -1.5010139577498194e-005 + 0.5324671268463135 + 0.3682988882064819 + <_> + + <_> + + + + <_>9 16 3 3 -1. + <_>9 17 3 1 3. + 0 + -4.2428788729012012e-003 + 0.6481474041938782 + 1 + <_> + + + + <_>8 14 6 3 -1. + <_>8 15 6 1 3. + 0 + 9.1374982148408890e-003 + 0.4896158874034882 + 0.6558843255043030 + <_> + + <_> + + + + <_>6 0 8 12 -1. + <_>6 0 4 6 2. + <_>10 6 4 6 2. + 0 + 8.8254585862159729e-003 + 1 + 0.3613870143890381 + <_> + + + + <_>4 12 2 3 -1. + <_>4 13 2 1 3. + 0 + 9.4092212384566665e-004 + 0.5502895712852478 + 0.3632518053054810 + <_> + + <_> + + + + <_>12 16 6 3 -1. + <_>12 17 6 1 3. + 0 + -0.0125033501535654 + 0.2261132001876831 + 1 + <_> + + + + <_>7 12 7 2 -1. + <_>7 13 7 1 2. + 0 + 8.6759645491838455e-003 + 0.4987890124320984 + 0.6847196221351624 + <_> + + <_> + + + + <_>2 16 6 3 -1. + <_>2 17 6 1 3. + 0 + -0.0104167601093650 + 0.2446299046278000 + 1 + <_> + + + + <_>0 7 16 6 -1. + <_>0 10 16 3 2. + 0 + 2.7432460337877274e-003 + 0.3511525094509125 + 0.5399826765060425 + <_> + + <_> + + + + <_>9 7 3 3 -1. + <_>10 7 1 3 3. + 0 + -4.2385691776871681e-003 + 0.6823673248291016 + 1 + <_> + + + + <_>9 7 3 5 -1. + <_>10 7 1 5 3. + 0 + 0.0183258708566427 + 0.4891580045223236 + 0.7135618925094605 + <_> + + <_> + + + + <_>0 5 20 10 -1. + <_>0 5 10 5 2. + <_>10 10 10 5 2. + 0 + -0.0243345405906439 + 0.3522521853446960 + 1 + <_> + + + + <_>3 1 4 2 -1. + <_>5 1 2 2 2. + 0 + 4.6469361404888332e-004 + 0.4049868881702423 + 0.5515825748443604 + <_> + + <_> + + + + <_>7 6 8 10 -1. + <_>11 6 4 5 2. + <_>7 11 4 5 2. + 0 + 3.4260009415447712e-003 + 1 + 0.4126769900321960 + <_> + + + + <_>17 6 3 2 -1. + <_>17 7 3 1 2. + 0 + -2.5827318895608187e-003 + 0.2899428904056549 + 0.5386431813240051 + <_> + + <_> + + + + <_>5 6 8 10 -1. + <_>5 6 4 5 2. + <_>9 11 4 5 2. + 0 + 1.0545699624344707e-003 + 1 + 0.3771344125270844 + <_> + + + + <_>5 12 10 6 -1. + <_>5 14 10 2 3. + 0 + -9.1257691383361816e-004 + 0.5827386975288391 + 0.4267556965351105 + <_> + + <_> + + + + <_>9 7 3 3 -1. + <_>10 7 1 3 3. + 0 + 2.6589010376483202e-003 + 0.4688124954700470 + 1 + <_> + + + + <_>10 3 2 6 -1. + <_>11 3 1 3 2. + <_>10 6 1 3 2. + 0 + 4.8598358407616615e-003 + 0.4853922128677368 + 0.6163644790649414 + <_> + + <_> + + + + <_>0 4 3 3 -1. + <_>0 5 3 1 3. + 0 + 8.0638676881790161e-003 + 1 + 0.1749195009469986 + <_> + + + + <_>3 16 8 4 -1. + <_>3 16 4 2 2. + <_>7 18 4 2 2. + 0 + -7.5898370705544949e-003 + 0.6826189756393433 + 0.4894070029258728 + <_> + + <_> + + + + <_>8 13 5 2 -1. + <_>8 14 5 1 2. + 0 + 3.6368070868775249e-004 + 0.4614596068859100 + 1 + <_> + + + + <_>8 7 4 12 -1. + <_>8 11 4 4 3. + 0 + 0.0625949501991272 + 0.5183017253875732 + 0.2686696052551270 + <_> + + <_> + + + + <_>5 9 2 2 -1. + <_>6 9 1 2 2. + 0 + -4.9753207713365555e-003 + 0.1758466958999634 + 1 + <_> + + + + <_>9 15 2 3 -1. + <_>9 16 2 1 3. + 0 + -2.0880119409412146e-003 + 0.6369382143020630 + 0.4930044114589691 + <_> + + <_> + + + + <_>13 9 2 3 -1. + <_>13 9 1 3 2. + 0 + 9.5644511748105288e-004 + 1 + 0.4139398932456970 + <_> + + + + <_>14 0 6 17 -1. + <_>16 0 2 17 3. + 0 + -0.0317214615643024 + 0.6045557260513306 + 0.4816364049911499 + <_> + + <_> + + + + <_>5 10 2 2 -1. + <_>6 10 1 2 2. + 0 + 1.2898689601570368e-003 + 0.5450810790061951 + 1 + <_> + + + + <_>2 9 9 1 -1. + <_>5 9 3 1 3. + 0 + 9.8405163735151291e-003 + 0.2924000918865204 + 0.6699606180191040 + <_> + + <_> + + + + <_>9 11 2 3 -1. + <_>9 12 2 1 3. + 0 + 1.2237089686095715e-003 + 1 + 0.6282836794853210 + <_> + + + + <_>7 11 6 3 -1. + <_>7 12 6 1 3. + 0 + -8.4232585504651070e-003 + 0.5986570119857788 + 0.4852580130100250 + <_> + + <_> + + + + <_>0 6 3 2 -1. + <_>0 7 3 1 2. + 0 + -7.2726322105154395e-004 + 0.3340049088001251 + 1 + <_> + + + + <_>7 0 6 1 -1. + <_>9 0 2 1 3. + 0 + 4.6842931769788265e-003 + 0.5168923735618591 + 0.2679480016231537 + <_> + + <_> + + + + <_>9 16 3 3 -1. + <_>9 17 3 1 3. + 0 + -1.0379579616710544e-003 + 0.5925791859626770 + 1 + <_> + + + + <_>2 13 17 6 -1. + <_>2 16 17 3 2. + 0 + 9.1342730447649956e-003 + 0.5437728166580200 + 0.4346800148487091 + <_> + + <_> + + + + <_>1 3 3 7 -1. + <_>2 3 1 7 3. + 0 + 1.4971119817346334e-003 + 0.4129500985145569 + 1 + <_> + + + + <_>1 1 6 4 -1. + <_>3 1 2 4 3. + 0 + 1.5762320253998041e-003 + 0.4522874057292938 + 0.6556292176246643 + <_> + + <_> + + + + <_>14 1 6 5 -1. + <_>14 1 3 5 2. + 0 + 8.7496247142553329e-003 + 0.4532034099102020 + 1 + <_> + + + + <_>13 2 3 2 -1. + <_>13 3 3 1 2. + 0 + -8.5103599121794105e-004 + 0.3785983920097351 + 0.5416975021362305 + <_> + + <_> + + + + <_>0 1 6 5 -1. + <_>3 1 3 5 2. + 0 + -0.0173255708068609 + 0.6884248256683350 + 1 + <_> + + + + <_>2 3 2 6 -1. + <_>2 5 2 2 3. + 0 + -8.3266440778970718e-003 + 0.3091326057910919 + 0.5243654847145081 + <_> + + <_> + + + + <_>9 10 3 2 -1. + <_>9 11 3 1 2. + 0 + 1.5157909729168750e-005 + 0.4765793979167938 + 1 + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 1.8041470320895314e-003 + 0.4725385904312134 + 0.5716555118560791 + <_> + + <_> + + + + <_>6 3 3 1 -1. + <_>7 3 1 1 3. + 0 + 3.0691560823470354e-003 + 1 + 0.2143359929323196 + <_> + + + + <_>8 2 3 12 -1. + <_>8 6 3 4 3. + 0 + -5.2225510444259271e-005 + 0.5653210282325745 + 0.4385111033916473 + <_> + + <_> + + + + <_>11 12 1 2 -1. + <_>11 13 1 1 2. + 0 + 1.0072169970953837e-004 + 1 + 0.5924776196479797 + <_> + + + + <_>11 12 2 2 -1. + <_>12 12 1 1 2. + <_>11 13 1 1 2. + 0 + 1.3573700562119484e-004 + 0.4573448896408081 + 0.5769382715225220 + <_> + + <_> + + + + <_>5 5 2 2 -1. + <_>5 6 2 1 2. + 0 + 9.2137878527864814e-004 + 1 + 0.5992609262466431 + <_> + + + + <_>5 4 1 3 -1. + <_>5 5 1 1 3. + 0 + 3.0316581251099706e-004 + 0.3610081076622009 + 0.5049325823783875 + <_> + + <_> + + + + <_>3 11 16 4 -1. + <_>11 11 8 2 2. + <_>3 13 8 2 2. + 0 + 0.0395824797451496 + 1 + 0.1538489013910294 + <_> + + + + <_>0 10 20 3 -1. + <_>0 11 20 1 3. + 0 + 0.0475196801126003 + 0.5216140747070313 + 0.1428391039371491 + <_> + + <_> + + + + <_>1 11 16 4 -1. + <_>1 11 8 2 2. + <_>9 13 8 2 2. + 0 + 0.0188717599958181 + 1 + 0.2825506925582886 + <_> + + + + <_>4 2 4 2 -1. + <_>4 3 4 1 2. + 0 + -3.9876459049992263e-004 + 0.4035016894340515 + 0.5437793135643005 + <_> + + <_> + + + + <_>12 6 2 2 -1. + <_>13 6 1 1 2. + <_>12 7 1 1 2. + 0 + 4.6556600136682391e-004 + 0.4668996930122376 + 1 + <_> + + + + <_>12 11 6 6 -1. + <_>12 13 6 2 3. + 0 + 6.7090610973536968e-003 + 0.5331354737281799 + 0.4136571884155273 + <_> + + <_> + + + + <_>6 6 2 2 -1. + <_>6 6 1 1 2. + <_>7 7 1 1 2. + 0 + -1.8931160448119044e-003 + 0.7155163288116455 + 1 + <_> + + + + <_>6 4 4 16 -1. + <_>8 4 2 16 2. + 0 + -0.0130569497123361 + 0.3117899894714356 + 0.5208439826965332 + <_> + + <_> + + + + <_>11 18 3 2 -1. + <_>11 19 3 1 2. + 0 + -1.9484119547996670e-004 + 1 + 0.4637658894062042 + <_> + + + + <_>9 17 6 2 -1. + <_>12 17 3 1 2. + <_>9 18 3 1 2. + 0 + 1.5093220099515747e-005 + 0.4561653137207031 + 0.5445234179496765 + <_> + + <_> + + + + <_>2 13 5 2 -1. + <_>2 14 5 1 2. + 0 + -7.1617960202274844e-006 + 1 + 0.4193108081817627 + <_> + + + + <_>3 15 2 2 -1. + <_>3 16 2 1 2. + 0 + 3.0164679628796875e-004 + 0.5966237783432007 + 0.4100500047206879 + <_> + + <_> + + + + <_>9 7 3 3 -1. + <_>10 7 1 3 3. + 0 + 4.4195181690156460e-003 + 0.4845055937767029 + 1 + <_> + + + + <_>9 6 2 6 -1. + <_>9 6 1 6 2. + 0 + -7.3984181508421898e-003 + 0.6206846237182617 + 0.4931209087371826 + <_> + + <_> + + + + <_>1 14 7 6 -1. + <_>1 16 7 2 3. + 0 + -7.8031201846897602e-003 + 1 + 0.5282462835311890 + <_> + + + + <_>8 1 2 11 -1. + <_>9 1 1 11 2. + 0 + -0.0107314297929406 + 0.9104834198951721 + 0.3455922007560730 + <_> + + <_> + + + + <_>9 7 2 4 -1. + <_>9 7 1 4 2. + 0 + 1.4246780192479491e-003 + 0.4708554148674011 + 1 + <_> + + + + <_>11 10 2 1 -1. + <_>11 10 1 1 2. + 0 + -8.2717568147927523e-005 + 0.5651623010635376 + 0.4731023907661438 + <_> + + <_> + + + + <_>0 3 3 9 -1. + <_>1 3 1 9 3. + 0 + 4.4803409837186337e-003 + 1 + 0.6175886988639832 + <_> + + + + <_>0 3 3 6 -1. + <_>0 5 3 2 3. + 0 + 3.0789140146225691e-003 + 0.5139533281326294 + 0.3423087894916534 + <_> + + <_> + + + + <_>11 15 2 2 -1. + <_>12 15 1 1 2. + <_>11 16 1 1 2. + 0 + -1.1310289846733212e-003 + 1 + 0.4918282032012940 + <_> + + + + <_>11 14 2 2 -1. + <_>12 14 1 1 2. + <_>11 15 1 1 2. + 0 + -1.0410690447315574e-003 + 0.5942087173461914 + 0.4923042953014374 + <_> + + <_> + + + + <_>7 15 2 2 -1. + <_>7 15 1 1 2. + <_>8 16 1 1 2. + 0 + 1.1648540385067463e-003 + 1 + 0.6405271887779236 + <_> + + + + <_>7 14 2 2 -1. + <_>7 14 1 1 2. + <_>8 15 1 1 2. + 0 + 9.0057362103834748e-004 + 0.4504396915435791 + 0.6192076802253723 + <_> + + <_> + + + + <_>8 13 4 6 -1. + <_>10 13 2 3 2. + <_>8 16 2 3 2. + 0 + 6.8781538866460323e-003 + 0.5374813079833984 + 1 + <_> + + + + <_>2 14 16 4 -1. + <_>10 14 8 2 2. + <_>2 16 8 2 2. + 0 + -0.0352839007973671 + 0.2247101068496704 + 0.5217170715332031 + <_> + + <_> + + + + <_>9 8 2 2 -1. + <_>9 9 2 1 2. + 0 + -1.3320200378075242e-003 + 0.2554703056812286 + 1 + <_> + + + + <_>7 7 5 3 -1. + <_>7 8 5 1 3. + 0 + -2.3177571129053831e-003 + 0.3792515993118286 + 0.5243226885795593 + <_> + + <_> + + + + <_>7 5 6 2 -1. + <_>9 5 2 2 3. + 0 + 2.1332940377760679e-004 + 0.3860337138175964 + 1 + <_> + + + + <_>9 1 6 18 -1. + <_>11 1 2 18 3. + 0 + 0.0134679004549980 + 0.5380687713623047 + 0.4178363978862763 + <_> + + <_> + + + + <_>8 6 3 4 -1. + <_>9 6 1 4 3. + 0 + -1.2829169863834977e-003 + 0.6133623123168945 + 1 + <_> + + + + <_>8 5 2 4 -1. + <_>8 5 1 2 2. + <_>9 7 1 2 2. + 0 + 5.1571638323366642e-004 + 0.4028537869453430 + 0.5536851882934570 + <_> + + <_> + + + + <_>9 13 2 6 -1. + <_>10 13 1 3 2. + <_>9 16 1 3 2. + 0 + 3.9254198782145977e-003 + 0.5279921293258667 + 1 + <_> + + + + <_>11 0 3 18 -1. + <_>12 0 1 18 3. + 0 + -0.0337805896997452 + 0.2334675043821335 + 0.5175911784172058 + <_> + + <_> + + + + <_>6 0 3 18 -1. + <_>7 0 1 18 3. + 0 + -0.0378537215292454 + 0.1074853017926216 + 1 + <_> + + + + <_>5 15 4 2 -1. + <_>7 15 2 2 2. + 0 + -4.0752900531515479e-004 + 0.5345929861068726 + 0.4198938012123108 + <_> + + <_> + + + + <_>1 9 18 1 -1. + <_>7 9 6 1 3. + 0 + -3.1193809118121862e-003 + 0.3855825066566467 + 1 + <_> + + + + <_>0 0 20 3 -1. + <_>0 1 20 1 3. + 0 + -0.0157149694859982 + 0.3335190117359161 + 0.5263202190399170 + <_> + + <_> + + + + <_>9 6 2 4 -1. + <_>10 6 1 4 2. + 0 + -7.8525702701881528e-004 + 0.5860397219657898 + 1 + <_> + + + + <_>6 10 6 2 -1. + <_>8 10 2 2 3. + 0 + -2.8750501223839819e-004 + 0.5437784790992737 + 0.3716104924678803 + <_> + + <_> + + + + <_>0 7 20 1 -1. + <_>0 7 10 1 2. + 0 + 0.0280168596655130 + 1 + 0.3330754935741425 + <_> + + + + <_>11 3 5 4 -1. + <_>11 5 5 2 2. + 0 + -1.9018839811906219e-003 + 0.5366597771644592 + 0.4693793952465057 + <_> + + <_> + + + + <_>5 7 10 1 -1. + <_>10 7 5 1 2. + 0 + 0.0206475593149662 + 1 + 0.1006956025958061 + <_> + + + + <_>8 10 3 3 -1. + <_>8 11 3 1 3. + 0 + 4.3002571910619736e-003 + 0.4816035926342011 + 0.6215677261352539 + <_> + + <_> + + + + <_>2 0 16 8 -1. + <_>10 0 8 4 2. + <_>2 4 8 4 2. + 0 + 0.0134591404348612 + 0.5461953878402710 + 1 + <_> + + + + <_>11 0 9 10 -1. + <_>11 5 9 5 2. + 0 + -0.0103200403973460 + 0.4578453004360199 + 0.5419309735298157 + <_> + + <_> + + + + <_>0 2 8 18 -1. + <_>4 2 4 18 2. + 0 + 0.3199074864387512 + 1 + 0.2008046954870224 + <_> + + + + <_>0 0 2 6 -1. + <_>0 2 2 2 3. + 0 + 9.2198798665776849e-004 + 0.5193281173706055 + 0.3912194073200226 + <_> + + <_> + + + + <_>6 0 9 2 -1. + <_>6 1 9 1 2. + 0 + 4.1852539288811386e-004 + 0.4299744069576263 + 1 + <_> + + + + <_>4 1 12 2 -1. + <_>4 2 12 1 2. + 0 + 3.5891108564101160e-004 + 0.4344502985477448 + 0.5531973838806152 + <_> + + <_> + + + + <_>2 1 16 14 -1. + <_>2 8 16 7 2. + 0 + -0.2099243998527527 + 0.1075721010565758 + 1 + <_> + + + + <_>5 1 8 12 -1. + <_>5 7 8 6 2. + 0 + -4.9328152090311050e-003 + 0.5762796998023987 + 0.4574643969535828 + <_> + + <_> + + + + <_>9 11 2 2 -1. + <_>9 12 2 1 2. + 0 + 2.3409130517393351e-003 + 1 + 0.7476807832717896 + <_> + + + + <_>9 10 5 6 -1. + <_>9 12 5 2 3. + 0 + 4.7120270319283009e-003 + 0.5261765122413635 + 0.4505550861358643 + <_> + + <_> + + + + <_>3 0 13 8 -1. + <_>3 4 13 4 2. + 0 + 0.0287131909281015 + 0.4407103061676025 + 1 + <_> + + + + <_>6 7 5 8 -1. + <_>6 11 5 4 2. + 0 + -2.6156550738960505e-003 + 0.4244270920753479 + 0.6892976760864258 + <_> + + <_> + + + + <_>9 5 2 3 -1. + <_>9 6 2 1 3. + 0 + -0.0135589698329568 + 0.1252267956733704 + 1 + <_> + + + + <_>6 8 8 3 -1. + <_>6 9 8 1 3. + 0 + -3.0331799644045532e-004 + 0.4077791869640350 + 0.5442817807197571 + <_> + + <_> + + + + <_>2 2 7 6 -1. + <_>2 5 7 3 2. + 0 + -5.5601762142032385e-004 + 0.5378003716468811 + 1 + <_> + + + + <_>2 1 14 4 -1. + <_>2 1 7 2 2. + <_>9 3 7 2 2. + 0 + 2.4025330785661936e-003 + 0.3166579902172089 + 0.5285738110542297 + <_> + + <_> + + + + <_>11 14 1 3 -1. + <_>11 15 1 1 3. + 0 + -3.4089901018887758e-003 + 1 + 0.4905214905738831 + <_> + + + + <_>6 15 8 2 -1. + <_>6 16 8 1 2. + 0 + 8.0019602319225669e-004 + 0.4522736072540283 + 0.5580614209175110 + <_> + + <_> + + + + <_>8 14 1 3 -1. + <_>8 15 1 1 3. + 0 + 2.1901070140302181e-003 + 1 + 0.6612681746482849 + <_> + + + + <_>8 11 2 8 -1. + <_>8 15 2 4 2. + 0 + 3.3745369873940945e-003 + 0.5107765197753906 + 0.3386929929256439 + <_> + + <_> + + + + <_>6 15 8 2 -1. + <_>6 16 8 1 2. + 0 + 8.0019602319225669e-004 + 1 + 0.5707560181617737 + <_> + + + + <_>7 16 8 3 -1. + <_>7 17 8 1 3. + 0 + 0.0173460692167282 + 0.5016021132469177 + 0.6306459903717041 + <_> + + <_> + + + + <_>0 16 2 2 -1. + <_>0 17 2 1 2. + 0 + -1.9568449351936579e-003 + 0.3017806112766266 + 1 + <_> + + + + <_>1 16 8 4 -1. + <_>1 16 4 2 2. + <_>5 18 4 2 2. + 0 + -0.0112290196120739 + 0.6293851137161255 + 0.4520488977432251 + <_> + + <_> + + + + <_>2 9 16 3 -1. + <_>2 10 16 1 3. + 0 + -2.6608388870954514e-003 + 0.3344007134437561 + 1 + <_> + + + + <_>13 11 2 4 -1. + <_>13 11 1 4 2. + 0 + -0.0116151003167033 + 0.2825379073619843 + 0.5150970816612244 + <_> + + <_> + + + + <_>0 13 16 6 -1. + <_>0 15 16 2 3. + 0 + -0.0952486023306847 + 0.1398265063762665 + 1 + <_> + + + + <_>5 11 2 4 -1. + <_>6 11 1 4 2. + 0 + 7.3701781220734119e-003 + 0.5293998718261719 + 0.2331728041172028 + <_> + + <_> + + + + <_>18 2 2 18 -1. + <_>19 2 1 9 2. + <_>18 11 1 9 2. + 0 + -0.0149539001286030 + 1 + 0.4940465986728668 + <_> + + + + <_>19 7 1 9 -1. + <_>19 10 1 3 3. + 0 + 5.7038792874664068e-004 + 0.5466570854187012 + 0.4626767933368683 + <_> + + <_> + + + + <_>0 2 2 18 -1. + <_>0 2 1 9 2. + <_>1 11 1 9 2. + 0 + 5.8516198769211769e-003 + 1 + 0.6270040869712830 + <_> + + + + <_>0 7 1 9 -1. + <_>0 10 1 3 3. + 0 + 2.1150549582671374e-004 + 0.5508140921592712 + 0.4061872959136963 + <_> + + <_> + + + + <_>14 12 2 2 -1. + <_>14 13 2 1 2. + 0 + -6.9679190346505493e-006 + 1 + 0.4096567928791046 + <_> + + + + <_>11 14 2 3 -1. + <_>11 15 2 1 3. + 0 + -7.9677387839183211e-004 + 0.5615556836128235 + 0.4666886031627655 + <_> + + <_> + + + + <_>7 8 6 2 -1. + <_>7 9 6 1 2. + 0 + 0.0194594804197550 + 1 + 0.2311480939388275 + <_> + + + + <_>7 12 4 6 -1. + <_>7 12 2 3 2. + <_>9 15 2 3 2. + 0 + -0.0111608300358057 + 0.3087011873722076 + 0.5514662265777588 + <_> + + <_> + + + + <_>8 13 5 3 -1. + <_>8 14 5 1 3. + 0 + 0.0140561498701572 + 1 + 0.7005056142807007 + <_> + + + + <_>12 14 2 2 -1. + <_>13 14 1 1 2. + <_>12 15 1 1 2. + 0 + -3.2958350493572652e-004 + 0.5797485709190369 + 0.4691650867462158 + <_> + + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -5.4636420682072639e-003 + 0.5928595066070557 + 1 + <_> + + + + <_>7 13 5 2 -1. + <_>7 14 5 1 2. + 0 + 5.8881669247057289e-005 + 0.3741397857666016 + 0.5170168876647949 + <_> + + <_> + + + + <_>2 10 16 4 -1. + <_>10 10 8 2 2. + <_>2 12 8 2 2. + 0 + 6.6343429498374462e-003 + 0.5414987802505493 + 1 + <_> + + + + <_>7 0 6 6 -1. + <_>9 0 2 6 3. + 0 + 0.0452634096145630 + 0.5180327296257019 + 0.1529684066772461 + <_> + + <_> + + + + <_>7 1 6 3 -1. + <_>7 2 6 1 3. + 0 + -8.0646127462387085e-003 + 0.2515468001365662 + 1 + <_> + + + + <_>0 12 6 2 -1. + <_>0 13 6 1 2. + 0 + 4.7389548853971064e-004 + 0.5121998786926270 + 0.3725948929786682 + <_> + + <_> + + + + <_>6 3 11 2 -1. + <_>6 4 11 1 2. + 0 + 1.4877359717502259e-005 + 1 + 0.5532435774803162 + <_> + + + + <_>12 0 8 6 -1. + <_>16 0 4 3 2. + <_>12 3 4 3 2. + 0 + 0.0243211593478918 + 0.4960766136646271 + 0.5983315110206604 + <_> + + <_> + + + + <_>8 12 1 2 -1. + <_>8 13 1 1 2. + 0 + 6.9931396865285933e-005 + 0.4163953065872192 + 1 + <_> + + + + <_>8 8 1 12 -1. + <_>8 12 1 4 3. + 0 + 2.6287760119885206e-003 + 0.5880144834518433 + 0.3399662971496582 + <_> + + <_> + + + + <_>11 11 2 2 -1. + <_>12 11 1 1 2. + <_>11 12 1 1 2. + 0 + 3.8190539926290512e-003 + 1 + 0.7846621274948120 + <_> + + + + <_>12 7 3 13 -1. + <_>13 7 1 13 3. + 0 + -0.0259891506284475 + 0.3288114070892334 + 0.5155087709426880 + <_> + + <_> + + + + <_>7 11 2 2 -1. + <_>7 11 1 1 2. + <_>8 12 1 1 2. + 0 + 1.2062400346621871e-003 + 0.4596059918403626 + 1 + <_> + + + + <_>3 13 1 3 -1. + <_>3 14 1 1 3. + 0 + -1.5557400183752179e-003 + 0.3126986920833588 + 0.7183399200439453 + <_> + + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + -2.2691930644214153e-003 + 1 + 0.5274006128311157 + <_> + + + + <_>11 11 2 1 -1. + <_>11 11 1 1 2. + 0 + 2.3287249496206641e-004 + 0.4878666102886200 + 0.5615152716636658 + <_> + + <_> + + + + <_>1 10 5 9 -1. + <_>1 13 5 3 3. + 0 + -5.5999699980020523e-003 + 1 + 0.5160812139511108 + <_> + + + + <_>4 8 6 4 -1. + <_>6 8 2 4 3. + 0 + -0.0104961898177862 + 0.5701614022254944 + 0.3204850852489471 + <_> + + <_> + + + + <_>13 12 1 4 -1. + <_>13 14 1 2 2. + 0 + -1.4814930182183161e-005 + 0.5538837909698486 + 1 + <_> + + + + <_>11 3 4 14 -1. + <_>13 3 2 7 2. + <_>11 10 2 7 2. + 0 + -6.4287078566849232e-004 + 0.5349429249763489 + 0.4472151100635529 + <_> + + <_> + + + + <_>6 12 1 4 -1. + <_>6 14 1 2 2. + 0 + -1.8891949730459601e-004 + 0.5012837052345276 + 1 + <_> + + + + <_>5 3 4 14 -1. + <_>5 3 2 7 2. + <_>7 10 2 7 2. + 0 + -9.0413521975278854e-003 + 0.2562935948371887 + 0.4503383040428162 + <_> + + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + 7.9534705728292465e-003 + 1 + 0.2630499899387360 + <_> + + + + <_>9 12 3 3 -1. + <_>9 13 3 1 3. + 0 + -2.7908999472856522e-003 + 0.5756508708000183 + 0.4854863882064819 + <_> + + <_> + + + + <_>2 2 12 6 -1. + <_>2 2 6 3 2. + <_>8 5 6 3 2. + 0 + 3.2857100013643503e-003 + 1 + 0.4084751904010773 + <_> + + + + <_>6 6 6 2 -1. + <_>9 6 3 2 2. + 0 + 7.7063008211553097e-004 + 0.4073356091976166 + 0.5920240879058838 + 44.6829681396484380 + 15 + -1 + <_> + + + <_> + + <_> + + + + <_>1 0 18 12 -1. + <_>7 0 6 12 3. + 0 + 0.0630219429731369 + 0.3419382870197296 + 1 + <_> + + + + <_>5 7 6 4 -1. + <_>5 7 3 2 2. + <_>8 9 3 2 2. + 0 + -2.8374609537422657e-003 + 0.6829563975334168 + 0.4404523074626923 + <_> + + <_> + + + + <_>5 7 10 4 -1. + <_>5 9 10 2 2. + 0 + 0.0464619509875774 + 0.4391745030879974 + 1 + <_> + + + + <_>7 7 6 4 -1. + <_>9 7 2 4 3. + 0 + 0.0291525404900312 + 0.4601063132286072 + 0.6357936859130859 + <_> + + <_> + + + + <_>9 5 2 2 -1. + <_>9 6 2 1 2. + 0 + -1.4000290320836939e-005 + 1 + 0.3730010092258453 + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + -1.2757079675793648e-003 + 0.3093824088573456 + 0.5901370048522949 + <_> + + <_> + + + + <_>6 17 8 3 -1. + <_>6 18 8 1 3. + 0 + 1.3596529606729746e-003 + 0.4337565004825592 + 1 + <_> + + + + <_>9 17 6 2 -1. + <_>12 17 3 1 2. + <_>9 18 3 1 2. + 0 + 1.7991929780691862e-004 + 0.4217503964900971 + 0.5846847891807556 + <_> + + <_> + + + + <_>4 12 2 2 -1. + <_>4 13 2 1 2. + 0 + -1.4166639630275313e-005 + 1 + 0.4084691107273102 + <_> + + + + <_>3 12 9 2 -1. + <_>3 13 9 1 2. + 0 + 6.0252390539972112e-005 + 0.5087286829948425 + 0.7277184128761292 + <_> + + <_> + + + + <_>8 3 6 1 -1. + <_>10 3 2 1 3. + 0 + 6.4320368692278862e-003 + 1 + 0.2967903017997742 + <_> + + + + <_>9 3 4 6 -1. + <_>11 3 2 3 2. + <_>9 6 2 3 2. + 0 + 4.6682319953106344e-004 + 0.4110462963581085 + 0.5581219792366028 + <_> + + <_> + + + + <_>0 3 6 5 -1. + <_>3 3 3 5 2. + 0 + 5.7436279021203518e-003 + 0.4287309944629669 + 1 + <_> + + + + <_>2 0 2 18 -1. + <_>2 6 2 6 3. + 0 + 3.2019240316003561e-003 + 0.4266195893287659 + 0.6444045901298523 + <_> + + <_> + + + + <_>14 2 4 9 -1. + <_>14 5 4 3 3. + 0 + -5.7637941790744662e-004 + 1 + 0.4084824919700623 + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + -3.7901920732110739e-003 + 0.3181920945644379 + 0.5230693221092224 + <_> + + <_> + + + + <_>2 2 4 9 -1. + <_>2 5 4 3 3. + 0 + 4.8914109356701374e-003 + 1 + 0.3548356890678406 + <_> + + + + <_>7 18 3 2 -1. + <_>8 18 1 2 3. + 0 + 4.6459292061626911e-003 + 0.5610597729682922 + 0.2693848907947540 + <_> + + <_> + + + + <_>10 14 3 3 -1. + <_>10 15 3 1 3. + 0 + -6.8799369037151337e-003 + 0.6235408186912537 + 1 + <_> + + + + <_>10 12 2 6 -1. + <_>10 15 2 3 2. + 0 + -0.0181474704295397 + 0.2861981987953186 + 0.5226848125457764 + <_> + + <_> + + + + <_>7 5 3 6 -1. + <_>7 7 3 2 3. + 0 + 1.1409220314817503e-004 + 1 + 0.3257833123207092 + <_> + + + + <_>3 3 6 2 -1. + <_>3 4 6 1 2. + 0 + -5.4334272863343358e-004 + 0.3882969021797180 + 0.5341166257858276 + <_> + + <_> + + + + <_>8 4 7 3 -1. + <_>8 5 7 1 3. + 0 + -2.7602489572018385e-003 + 0.6353965997695923 + 1 + <_> + + + + <_>13 6 2 3 -1. + <_>13 7 2 1 3. + 0 + -1.9730569329112768e-003 + 0.5880761146545410 + 0.4593090116977692 + <_> + + <_> + + + + <_>8 8 2 12 -1. + <_>8 12 2 4 3. + 0 + 2.4565239436924458e-003 + 1 + 0.3134010136127472 + <_> + + + + <_>5 4 8 14 -1. + <_>5 4 4 7 2. + <_>9 11 4 7 2. + 0 + 1.9392010290175676e-004 + 0.5277131795883179 + 0.3604106903076172 + <_> + + <_> + + + + <_>0 1 20 8 -1. + <_>10 1 10 4 2. + <_>0 5 10 4 2. + 0 + 0.0786430165171623 + 0.5290341973304749 + 1 + <_> + + + + <_>4 0 12 2 -1. + <_>4 1 12 1 2. + 0 + 6.5276869572699070e-003 + 0.4654479920864105 + 0.6044905185699463 + <_> + + <_> + + + + <_>0 1 20 8 -1. + <_>0 1 10 4 2. + <_>10 5 10 4 2. + 0 + -0.0787167996168137 + 0.2541126906871796 + 1 + <_> + + + + <_>4 0 12 2 -1. + <_>4 1 12 1 2. + 0 + 5.7298499159514904e-003 + 0.4366919100284576 + 0.5822886228561401 + <_> + + <_> + + + + <_>9 5 6 3 -1. + <_>9 5 3 3 2. + 0 + 6.2386557692661881e-004 + 1 + 0.5472692251205444 + <_> + + + + <_>8 13 10 6 -1. + <_>8 15 10 2 3. + 0 + -0.0852672308683395 + 0.1461607962846756 + 0.5181810855865479 + <_> + + <_> + + + + <_>5 5 6 3 -1. + <_>8 5 3 3 2. + 0 + 0.0409811101853848 + 1 + 0.1270135045051575 + <_> + + + + <_>6 3 6 1 -1. + <_>8 3 2 1 3. + 0 + 7.7135749161243439e-003 + 0.4832684993743897 + 0.2223578989505768 + <_> + + <_> + + + + <_>11 18 9 2 -1. + <_>14 18 3 2 3. + 0 + -6.8663940764963627e-003 + 0.5918928980827332 + 1 + <_> + + + + <_>13 11 6 7 -1. + <_>13 11 3 7 2. + 0 + 0.0145596396178007 + 0.4761506915092468 + 0.5727223753929138 + <_> + + <_> + + + + <_>4 6 12 10 -1. + <_>4 6 6 5 2. + <_>10 11 6 5 2. + 0 + -0.0100643103942275 + 0.3636730909347534 + 1 + <_> + + + + <_>8 17 3 3 -1. + <_>9 17 1 3 3. + 0 + 3.6274080630391836e-003 + 0.5271731019020081 + 0.2740525007247925 + <_> + + <_> + + + + <_>11 18 9 2 -1. + <_>14 18 3 2 3. + 0 + -2.3421540390700102e-003 + 0.5497784018516541 + 1 + <_> + + + + <_>13 11 6 8 -1. + <_>13 11 3 8 2. + 0 + -0.0246864091604948 + 0.6059895157814026 + 0.4960314035415649 + <_> + + <_> + + + + <_>4 16 2 2 -1. + <_>4 17 2 1 2. + 0 + 1.9456120207905769e-004 + 1 + 0.3769465088844299 + <_> + + + + <_>7 15 4 4 -1. + <_>7 17 4 2 2. + 0 + 3.1714211218059063e-004 + 0.4062362015247345 + 0.5668215155601502 + <_> + + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + 2.0793990697711706e-003 + 0.4618656933307648 + 1 + <_> + + + + <_>13 6 2 3 -1. + <_>13 7 2 1 3. + 0 + 1.7982709687203169e-003 + 0.4867505133152008 + 0.6518449783325195 + <_> + + <_> + + + + <_>5 11 6 1 -1. + <_>7 11 2 1 3. + 0 + -2.2287059982772917e-004 + 0.5677595734596252 + 1 + <_> + + + + <_>7 10 3 1 -1. + <_>8 10 1 1 3. + 0 + 3.2623921288177371e-004 + 0.3710733950138092 + 0.5676605105400085 + <_> + + <_> + + + + <_>0 12 20 4 -1. + <_>0 14 20 2 2. + 0 + -0.0667926818132401 + 0.2511521875858307 + 1 + <_> + + + + <_>10 2 3 2 -1. + <_>10 3 3 1 2. + 0 + -1.4869889710098505e-003 + 0.3886750936508179 + 0.5262253880500794 + <_> + + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + -5.0454870797693729e-003 + 0.6557472944259644 + 1 + <_> + + + + <_>5 5 4 3 -1. + <_>5 6 4 1 3. + 0 + -4.8297587782144547e-003 + 0.5934106111526489 + 0.4285922050476074 + <_> + + <_> + + + + <_>8 8 4 3 -1. + <_>8 9 4 1 3. + 0 + -1.0722599690780044e-003 + 1 + 0.5426058769226074 + <_> + + + + <_>10 4 2 12 -1. + <_>10 8 2 4 3. + 0 + 8.7901195511221886e-003 + 0.5351303219795227 + 0.4834277927875519 + <_> + + <_> + + + + <_>0 3 4 3 -1. + <_>0 4 4 1 3. + 0 + -7.1750381030142307e-003 + 0.2067168951034546 + 1 + <_> + + + + <_>1 3 2 3 -1. + <_>1 4 2 1 3. + 0 + 1.1251230025663972e-003 + 0.5112252235412598 + 0.3468714058399200 + <_> + + <_> + + + + <_>16 1 4 11 -1. + <_>16 1 2 11 2. + 0 + 0.0106347100809217 + 0.4479008018970490 + 1 + <_> + + + + <_>18 2 2 16 -1. + <_>19 2 1 8 2. + <_>18 10 1 8 2. + 0 + -0.0117632197216153 + 0.6253901720046997 + 0.4968987107276917 + <_> + + <_> + + + + <_>1 8 6 12 -1. + <_>3 8 2 12 3. + 0 + 0.0923240631818771 + 1 + 0.2031303942203522 + <_> + + + + <_>7 2 6 2 -1. + <_>7 2 3 1 2. + <_>10 3 3 1 2. + 0 + 1.8991080578416586e-003 + 0.5618721842765808 + 0.4046572148799896 + <_> + + <_> + + + + <_>12 4 8 2 -1. + <_>16 4 4 1 2. + <_>12 5 4 1 2. + 0 + -0.0105103403329849 + 1 + 0.4943264126777649 + <_> + + + + <_>10 6 6 2 -1. + <_>12 6 2 2 3. + 0 + -7.4531312566250563e-004 + 0.5613427758216858 + 0.3845331966876984 + <_> + + <_> + + + + <_>0 4 8 2 -1. + <_>0 4 4 1 2. + <_>4 5 4 1 2. + 0 + 8.0041000619530678e-003 + 1 + 0.7759842276573181 + <_> + + + + <_>1 3 3 5 -1. + <_>2 3 1 5 3. + 0 + 5.8110528625547886e-003 + 0.4624733030796051 + 0.6286277174949646 + <_> + + <_> + + + + <_>16 3 4 6 -1. + <_>16 5 4 2 3. + 0 + -0.0279185809195042 + 0.2409314066171646 + 1 + <_> + + + + <_>8 6 4 3 -1. + <_>8 7 4 1 3. + 0 + 2.1739399526268244e-003 + 0.5345504879951477 + 0.3507958054542542 + <_> + + <_> + + + + <_>8 14 1 3 -1. + <_>8 15 1 1 3. + 0 + -4.0639587678015232e-003 + 0.6647101044654846 + 1 + <_> + + + + <_>4 11 1 2 -1. + <_>4 12 1 1 2. + 0 + 6.0017139185220003e-004 + 0.4998509883880615 + 0.3022165000438690 + <_> + + <_> + + + + <_>8 14 6 3 -1. + <_>8 15 6 1 3. + 0 + 1.9214770291000605e-003 + 1 + 0.5919150710105896 + <_> + + + + <_>7 15 7 3 -1. + <_>7 16 7 1 3. + 0 + -0.0138608301058412 + 0.6351767778396606 + 0.4993310868740082 + <_> + + <_> + + + + <_>9 12 2 8 -1. + <_>9 16 2 4 2. + 0 + 0.0230068508535624 + 1 + 0.1902336031198502 + <_> + + + + <_>4 6 6 2 -1. + <_>6 6 2 2 3. + 0 + -1.3857929734513164e-003 + 0.5253369212150574 + 0.3985860049724579 + <_> + + <_> + + + + <_>12 7 4 2 -1. + <_>12 8 4 1 2. + 0 + 1.2637410545721650e-003 + 0.4666104018688202 + 1 + <_> + + + + <_>5 3 13 10 -1. + <_>5 8 13 5 2. + 0 + -0.0146752102300525 + 0.3823164999485016 + 0.5326632857322693 + <_> + + <_> + + + + <_>4 7 4 2 -1. + <_>4 8 4 1 2. + 0 + -2.9535070061683655e-003 + 0.7063655853271484 + 1 + <_> + + + + <_>0 8 16 2 -1. + <_>0 8 8 1 2. + <_>8 9 8 1 2. + 0 + -1.7189770005643368e-003 + 0.3813462853431702 + 0.5246735215187073 + <_> + + <_> + + + + <_>11 8 2 5 -1. + <_>11 8 1 5 2. + 0 + -4.2484089499339461e-004 + 1 + 0.4791638851165772 + <_> + + + + <_>10 0 6 13 -1. + <_>10 0 3 13 2. + 0 + -8.5248658433556557e-004 + 0.4491218030452728 + 0.5370901226997376 + <_> + + <_> + + + + <_>1 6 4 2 -1. + <_>1 7 4 1 2. + 0 + 8.9034568518400192e-003 + 1 + 0.2076473981142044 + <_> + + + + <_>4 3 2 1 -1. + <_>5 3 1 1 2. + 0 + 1.4895649655954912e-005 + 0.4447635114192963 + 0.5667163133621216 + <_> + + <_> + + + + <_>11 8 2 5 -1. + <_>11 8 1 5 2. + 0 + -4.7091601300053298e-004 + 0.5465071201324463 + 1 + <_> + + + + <_>12 10 4 8 -1. + <_>12 10 2 8 2. + 0 + 4.3084810022264719e-004 + 0.5493261814117432 + 0.4580708146095276 + <_> + + <_> + + + + <_>7 8 2 5 -1. + <_>8 8 1 5 2. + 0 + -6.3893961487337947e-004 + 0.5501571893692017 + 1 + <_> + + + + <_>4 10 4 8 -1. + <_>6 10 2 8 2. + 0 + -7.3733746830839664e-005 + 0.5085790753364563 + 0.3305698037147522 + <_> + + <_> + + + + <_>6 7 9 12 -1. + <_>9 7 3 12 3. + 0 + -8.8991485536098480e-003 + 0.4276469051837921 + 1 + <_> + + + + <_>11 13 2 3 -1. + <_>11 13 1 3 2. + 0 + -0.0102533502504230 + 0.1123218014836311 + 0.5152723193168640 + <_> + + <_> + + + + <_>7 10 6 10 -1. + <_>10 10 3 10 2. + 0 + -0.0596374906599522 + 0.7386772036552429 + 1 + <_> + + + + <_>8 11 4 8 -1. + <_>8 11 2 4 2. + <_>10 15 2 4 2. + 0 + 0.0217071995139122 + 0.4996291995048523 + 0.1339413970708847 + <_> + + <_> + + + + <_>16 1 4 11 -1. + <_>16 1 2 11 2. + 0 + 9.9107045680284500e-003 + 0.4679012000560761 + 1 + <_> + + + + <_>18 2 2 4 -1. + <_>18 2 1 4 2. + 0 + -0.0109983002766967 + 0.6928656101226807 + 0.5012068152427673 + <_> + + <_> + + + + <_>5 6 6 2 -1. + <_>5 6 3 1 2. + <_>8 7 3 1 2. + 0 + 7.4608891736716032e-004 + 1 + 0.5833582282066345 + <_> + + + + <_>5 4 1 3 -1. + <_>5 5 1 1 3. + 0 + 2.9539171373471618e-004 + 0.3826391100883484 + 0.5566350817680359 + <_> + + <_> + + + + <_>11 1 4 14 -1. + <_>11 1 2 14 2. + 0 + 0.0500541292130947 + 1 + 0.3002721071243286 + <_> + + + + <_>4 2 12 3 -1. + <_>8 2 4 3 3. + 0 + -7.2330660186707973e-003 + 0.5908042788505554 + 0.5000870823860169 + <_> + + <_> + + + + <_>5 1 4 14 -1. + <_>7 1 2 14 2. + 0 + -2.6863380335271358e-003 + 0.3975034952163696 + 1 + <_> + + + + <_>7 3 6 2 -1. + <_>9 3 2 2 3. + 0 + -1.0195849463343620e-003 + 0.3697685897350311 + 0.5756192803382874 + <_> + + <_> + + + + <_>2 0 18 4 -1. + <_>8 0 6 4 3. + 0 + -0.0202049203217030 + 0.6375268101692200 + 1 + <_> + + + + <_>9 5 2 10 -1. + <_>9 10 2 5 2. + 0 + 2.1340379025787115e-003 + 0.5363265872001648 + 0.4433170855045319 + <_> + + <_> + + + + <_>8 6 3 4 -1. + <_>9 6 1 4 3. + 0 + -1.8348889425396919e-003 + 0.5828999280929565 + 1 + <_> + + + + <_>5 5 9 11 -1. + <_>8 5 3 11 3. + 0 + -5.9489468112587929e-003 + 0.2680670917034149 + 0.4642885923385620 + <_> + + <_> + + + + <_>10 6 3 5 -1. + <_>11 6 1 5 3. + 0 + -2.3030120064504445e-004 + 0.5475320219993591 + 1 + <_> + + + + <_>8 9 6 5 -1. + <_>8 9 3 5 2. + 0 + 5.0581009127199650e-003 + 0.5320833921432495 + 0.4646492898464203 + <_> + + <_> + + + + <_>7 6 3 5 -1. + <_>8 6 1 5 3. + 0 + -5.1950011402368546e-004 + 0.5232744812965393 + 1 + <_> + + + + <_>6 10 6 3 -1. + <_>9 10 3 3 2. + 0 + -6.8620947422459722e-004 + 0.4935086071491242 + 0.3103117942810059 + <_> + + <_> + + + + <_>10 0 3 7 -1. + <_>11 0 1 7 3. + 0 + -7.4936267919838428e-003 + 0.2883046865463257 + 1 + <_> + + + + <_>0 3 20 12 -1. + <_>0 9 20 6 2. + 0 + -0.0156829301267862 + 0.3640313148498535 + 0.5368754863739014 + <_> + + <_> + + + + <_>9 7 2 2 -1. + <_>10 7 1 2 2. + 0 + -3.2649750355631113e-003 + 0.6468631029129028 + 1 + <_> + + + + <_>5 9 4 1 -1. + <_>7 9 2 1 2. + 0 + 3.8463930832222104e-004 + 0.5259659886360169 + 0.3831427991390228 + <_> + + <_> + + + + <_>13 13 3 2 -1. + <_>13 14 3 1 2. + 0 + 4.4492390006780624e-003 + 1 + 0.2086818963289261 + <_> + + + + <_>16 9 4 6 -1. + <_>16 9 2 6 2. + 0 + 0.0231183208525181 + 0.4978533089160919 + 0.5961257219314575 + <_> + + <_> + + + + <_>7 15 6 3 -1. + <_>7 16 6 1 3. + 0 + 2.0835159812122583e-003 + 1 + 0.5746421813964844 + <_> + + + + <_>6 16 7 3 -1. + <_>6 17 7 1 3. + 0 + 1.1513150529935956e-003 + 0.3586845099925995 + 0.5363473892211914 + <_> + + <_> + + + + <_>11 14 9 6 -1. + <_>11 16 9 2 3. + 0 + 0.0361047089099884 + 1 + 0.2833136916160584 + <_> + + + + <_>19 14 1 3 -1. + <_>19 15 1 1 3. + 0 + 3.6256198654882610e-004 + 0.5477722287178040 + 0.4110532104969025 + <_> + + <_> + + + + <_>0 9 6 6 -1. + <_>3 9 3 6 2. + 0 + -3.4635469783097506e-003 + 0.5990386009216309 + 1 + <_> + + + + <_>0 19 9 1 -1. + <_>3 19 3 1 3. + 0 + -2.8796829283237457e-003 + 0.5725253224372864 + 0.4149512052536011 + <_> + + <_> + + + + <_>11 14 9 6 -1. + <_>11 16 9 2 3. + 0 + -8.1119500100612640e-003 + 1 + 0.5396351814270020 + <_> + + + + <_>12 12 6 6 -1. + <_>12 14 6 2 3. + 0 + 4.5932079665362835e-003 + 0.5379704236984253 + 0.3891302943229675 + <_> + + <_> + + + + <_>1 14 8 6 -1. + <_>1 16 8 2 3. + 0 + 7.0014740340411663e-003 + 1 + 0.3714671134948731 + <_> + + + + <_>8 1 3 2 -1. + <_>9 1 1 2 3. + 0 + 8.0169539432972670e-004 + 0.5529567003250122 + 0.3755804896354675 + <_> + + <_> + + + + <_>18 2 2 4 -1. + <_>18 2 1 4 2. + 0 + -8.6652329191565514e-003 + 1 + 0.5025773048400879 + <_> + + + + <_>14 0 6 3 -1. + <_>16 0 2 3 3. + 0 + -2.7315050829201937e-003 + 0.5850322246551514 + 0.4617573916912079 + <_> + + <_> + + + + <_>0 2 2 4 -1. + <_>1 2 1 4 2. + 0 + 1.3301590224727988e-003 + 1 + 0.5937700867652893 + <_> + + + + <_>0 0 6 3 -1. + <_>2 0 2 3 3. + 0 + -4.2648240923881531e-003 + 0.5645368099212647 + 0.3937624990940094 + <_> + + <_> + + + + <_>9 0 3 2 -1. + <_>10 0 1 2 3. + 0 + 6.3251499086618423e-003 + 0.5182105898857117 + 1 + <_> + + + + <_>12 1 2 2 -1. + <_>12 1 1 2 2. + 0 + -3.0753740575164557e-003 + 0.3007416129112244 + 0.5196403861045837 + <_> + + <_> + + + + <_>8 0 3 2 -1. + <_>9 0 1 2 3. + 0 + -7.3622138006612659e-004 + 0.3697580099105835 + 1 + <_> + + + + <_>6 1 2 2 -1. + <_>7 1 1 2 2. + 0 + 3.0082479497650638e-005 + 0.4327593147754669 + 0.5715808868408203 + <_> + + <_> + + + + <_>10 8 2 3 -1. + <_>10 9 2 1 3. + 0 + -3.8722730241715908e-003 + 0.3473713099956513 + 1 + <_> + + + + <_>13 15 6 2 -1. + <_>13 16 6 1 2. + 0 + 6.2879058532416821e-004 + 0.5438259243965149 + 0.4453906118869782 + <_> + + <_> + + + + <_>8 12 2 2 -1. + <_>8 12 1 1 2. + <_>9 13 1 1 2. + 0 + 1.3411579420790076e-003 + 1 + 0.6511713862419128 + <_> + + + + <_>8 15 3 5 -1. + <_>9 15 1 5 3. + 0 + -8.3681922405958176e-003 + 0.1443295031785965 + 0.4888199865818024 + <_> + + <_> + + + + <_>8 6 4 12 -1. + <_>8 12 4 6 2. + 0 + 9.3305751215666533e-004 + 1 + 0.3951109051704407 + <_> + + + + <_>7 6 7 8 -1. + <_>7 10 7 4 2. + 0 + -1.0746510233730078e-003 + 0.3910265862941742 + 0.5349503755569458 + <_> + + <_> + + + + <_>0 11 8 2 -1. + <_>0 12 8 1 2. + 0 + -0.0186100509017706 + 0.1275743991136551 + 1 + <_> + + + + <_>8 11 2 2 -1. + <_>8 11 1 1 2. + <_>9 12 1 1 2. + 0 + 1.3651419430971146e-003 + 0.5038288831710815 + 0.6951304078102112 + <_> + + <_> + + + + <_>7 7 12 1 -1. + <_>11 7 4 1 3. + 0 + 7.3744421824812889e-003 + 0.5253443121910095 + 1 + <_> + + + + <_>10 8 3 2 -1. + <_>11 8 1 2 3. + 0 + 8.4163323044776917e-003 + 0.5011243820190430 + 0.7311332821846008 + <_> + + <_> + + + + <_>1 7 12 1 -1. + <_>5 7 4 1 3. + 0 + 5.1413988694548607e-003 + 0.4953536093235016 + 1 + <_> + + + + <_>6 5 8 2 -1. + <_>6 5 4 1 2. + <_>10 6 4 1 2. + 0 + 4.5847031287848949e-003 + 0.2535555958747864 + 0.6462442874908447 + <_> + + <_> + + + + <_>9 10 3 10 -1. + <_>10 10 1 10 3. + 0 + 0.0285652391612530 + 1 + 0.2330722063779831 + <_> + + + + <_>16 0 2 4 -1. + <_>16 0 1 4 2. + 0 + 4.3958800961263478e-004 + 0.4702244102954865 + 0.5544549226760864 + <_> + + <_> + + + + <_>8 10 3 10 -1. + <_>9 10 1 10 3. + 0 + 0.0314594581723213 + 1 + 0.0336896888911724 + <_> + + + + <_>9 10 2 3 -1. + <_>9 11 2 1 3. + 0 + 5.6011630222201347e-003 + 0.4787121117115021 + 0.6338351964950562 + <_> + + <_> + + + + <_>8 9 4 2 -1. + <_>10 9 2 1 2. + <_>8 10 2 1 2. + 0 + 7.1835669223219156e-004 + 0.5431486964225769 + 1 + <_> + + + + <_>12 14 7 6 -1. + <_>12 16 7 2 3. + 0 + -5.5303089320659637e-003 + 0.4105832874774933 + 0.5403990745544434 + <_> + + <_> + + + + <_>6 1 3 1 -1. + <_>7 1 1 1 3. + 0 + 1.4129279879853129e-003 + 1 + 0.3105539977550507 + <_> + + + + <_>2 0 2 4 -1. + <_>3 0 1 4 2. + 0 + 2.5530709535814822e-004 + 0.4254471957683563 + 0.5447154045104981 + <_> + + <_> + + + + <_>11 11 2 2 -1. + <_>12 11 1 1 2. + <_>11 12 1 1 2. + 0 + 3.1966410460881889e-004 + 1 + 0.6118361949920654 + <_> + + + + <_>12 12 6 6 -1. + <_>12 14 6 2 3. + 0 + 5.0411392003297806e-003 + 0.5290042161941528 + 0.4224787056446075 + <_> + + <_> + + + + <_>1 0 6 10 -1. + <_>1 0 3 5 2. + <_>4 5 3 5 2. + 0 + 7.7617880888283253e-003 + 0.4315345883369446 + 1 + <_> + + + + <_>3 0 2 9 -1. + <_>3 3 2 3 3. + 0 + 2.9374631121754646e-003 + 0.6629263162612915 + 0.3028964996337891 + <_> + + <_> + + + + <_>14 13 3 2 -1. + <_>14 14 3 1 2. + 0 + -1.6497720498591661e-003 + 1 + 0.5491852760314941 + <_> + + + + <_>15 2 3 2 -1. + <_>15 3 3 1 2. + 0 + -5.8834417723119259e-003 + 0.3188554048538208 + 0.5184289216995239 + <_> + + <_> + + + + <_>2 13 5 2 -1. + <_>2 14 5 1 2. + 0 + 8.7459187489002943e-004 + 1 + 0.3328830897808075 + <_> + + + + <_>3 4 12 10 -1. + <_>3 4 6 5 2. + <_>9 9 6 5 2. + 0 + -0.0153087796643376 + 0.3923608064651489 + 0.5235139131546021 + <_> + + <_> + + + + <_>5 1 14 6 -1. + <_>5 3 14 2 3. + 0 + 0.0322924517095089 + 1 + 0.5977646708488464 + <_> + + + + <_>15 3 3 2 -1. + <_>15 4 3 1 2. + 0 + -4.3842519517056644e-004 + 0.4541687965393066 + 0.5369428992271423 + <_> + + <_> + + + + <_>7 11 2 2 -1. + <_>7 11 1 1 2. + <_>8 12 1 1 2. + 0 + 1.5429529594257474e-003 + 1 + 0.6318141222000122 + <_> + + + + <_>2 14 6 6 -1. + <_>2 16 6 2 3. + 0 + -2.4733028840273619e-003 + 0.3490633070468903 + 0.4759024977684021 + <_> + + <_> + + + + <_>6 13 8 3 -1. + <_>6 14 8 1 3. + 0 + 2.0994939841330051e-003 + 1 + 0.5887197852134705 + <_> + + + + <_>1 19 18 1 -1. + <_>7 19 6 1 3. + 0 + -5.7541108690202236e-003 + 0.5961331725120544 + 0.4841983020305634 + <_> + + <_> + + + + <_>8 12 1 6 -1. + <_>8 15 1 3 2. + 0 + -0.0102331303060055 + 0.1705404072999954 + 1 + <_> + + + + <_>0 0 14 15 -1. + <_>0 5 14 5 3. + 0 + 0.2255450934171677 + 0.4779379963874817 + 0.0978796631097794 + <_> + + <_> + + + + <_>3 0 16 8 -1. + <_>3 4 16 4 2. + 0 + 0.0296665597707033 + 1 + 0.5822224020957947 + <_> + + + + <_>6 1 8 12 -1. + <_>6 7 8 6 2. + 0 + -2.8518449980765581e-003 + 0.5459626913070679 + 0.4610066115856171 + <_> + + <_> + + + + <_>5 3 3 3 -1. + <_>6 3 1 3 3. + 0 + 9.7465328872203827e-004 + 1 + 0.3670322895050049 + <_> + + + + <_>5 1 3 4 -1. + <_>6 1 1 4 3. + 0 + 1.4044740055396687e-005 + 0.4302386045455933 + 0.5691710710525513 + <_> + + <_> + + + + <_>15 14 4 6 -1. + <_>17 14 2 3 2. + <_>15 17 2 3 2. + 0 + -0.0175794307142496 + 0.6917321085929871 + 1 + <_> + + + + <_>12 11 6 8 -1. + <_>15 11 3 4 2. + <_>12 15 3 4 2. + 0 + -0.0523816794157028 + 0.7110040187835693 + 0.5060154795646668 + <_> + + <_> + + + + <_>8 7 2 4 -1. + <_>9 7 1 4 2. + 0 + -0.0112421102821827 + 0.8769189119338989 + 1 + <_> + + + + <_>6 11 3 1 -1. + <_>7 11 1 1 3. + 0 + -3.6728400737047195e-003 + 0.6519191861152649 + 0.4546068906784058 + <_> + + <_> + + + + <_>12 3 2 14 -1. + <_>12 3 1 14 2. + 0 + 3.5082760732620955e-003 + 0.5329865813255310 + 1 + <_> + + + + <_>12 11 6 2 -1. + <_>15 11 3 1 2. + <_>12 12 3 1 2. + 0 + 6.1679710634052753e-003 + 0.5220459103584290 + 0.2953518927097321 + <_> + + <_> + + + + <_>0 2 5 2 -1. + <_>0 3 5 1 2. + 0 + -9.7009900491684675e-004 + 1 + 0.5048633217811585 + <_> + + + + <_>0 0 15 1 -1. + <_>5 0 5 1 3. + 0 + -0.0109570100903511 + 0.5837358236312866 + 0.3020085990428925 + <_> + + <_> + + + + <_>12 11 6 2 -1. + <_>15 11 3 1 2. + <_>12 12 3 1 2. + 0 + -8.3272513002157211e-003 + 0.3158063888549805 + 1 + <_> + + + + <_>10 5 2 2 -1. + <_>10 5 1 2 2. + 0 + 2.9798380637657829e-005 + 0.4386389851570129 + 0.5443211197853088 + <_> + + <_> + + + + <_>9 7 2 2 -1. + <_>10 7 1 2 2. + 0 + 2.8244039276614785e-004 + 1 + 0.5625395774841309 + <_> + + + + <_>9 0 2 10 -1. + <_>9 0 1 5 2. + <_>10 5 1 5 2. + 0 + -8.1364117795601487e-004 + 0.5281198024749756 + 0.3401407897472382 + <_> + + <_> + + + + <_>18 14 2 2 -1. + <_>18 15 2 1 2. + 0 + 1.8008040497079492e-003 + 1 + 0.3471659123897553 + <_> + + + + <_>13 11 4 9 -1. + <_>13 14 4 3 3. + 0 + -6.9944779388606548e-003 + 0.4481697082519531 + 0.5385770201683044 + <_> + + <_> + + + + <_>8 13 2 2 -1. + <_>8 13 1 1 2. + <_>9 14 1 1 2. + 0 + 4.5625398342963308e-005 + 0.4492512941360474 + 1 + <_> + + + + <_>7 8 4 3 -1. + <_>7 9 4 1 3. + 0 + -7.3189922841265798e-004 + 0.4167312085628510 + 0.6021102070808411 + <_> + + <_> + + + + <_>8 9 4 2 -1. + <_>8 10 4 1 2. + 0 + -2.9980219551362097e-004 + 0.4148428142070770 + 1 + <_> + + + + <_>13 12 4 2 -1. + <_>13 13 4 1 2. + 0 + -2.9060940505587496e-005 + 0.5592089891433716 + 0.4073210954666138 + <_> + + <_> + + + + <_>6 14 2 2 -1. + <_>6 14 1 1 2. + <_>7 15 1 1 2. + 0 + -5.9742690064013004e-004 + 0.6088914275169373 + 1 + <_> + + + + <_>0 14 2 2 -1. + <_>0 15 2 1 2. + 0 + 1.4831830048933625e-004 + 0.5298305153846741 + 0.3761950135231018 + <_> + + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -2.9441029764711857e-003 + 1 + 0.4716084897518158 + <_> + + + + <_>7 9 10 6 -1. + <_>7 11 10 2 3. + 0 + 0.1374121010303497 + 0.5101336836814880 + 0.0467468015849590 + <_> + + <_> + + + + <_>2 9 12 4 -1. + <_>6 9 4 4 3. + 0 + -0.0884141772985458 + 0.1181868985295296 + 1 + <_> + + + + <_>7 9 6 11 -1. + <_>10 9 3 11 2. + 0 + 0.0706102773547173 + 0.5119063258171082 + 0.7778441905975342 + <_> + + <_> + + + + <_>9 7 2 3 -1. + <_>9 8 2 1 3. + 0 + -7.7188978902995586e-003 + 0.1874134987592697 + 1 + <_> + + + + <_>9 14 4 3 -1. + <_>9 15 4 1 3. + 0 + 0.0151153998449445 + 0.4980027973651886 + 0.7005817890167236 + <_> + + <_> + + + + <_>2 3 3 17 -1. + <_>3 3 1 17 3. + 0 + 1.0671879863366485e-003 + 0.4482238888740540 + 1 + <_> + + + + <_>0 11 6 3 -1. + <_>0 12 6 1 3. + 0 + 7.0487911580130458e-004 + 0.6265752911567688 + 0.4402655065059662 + 47.7634506225585940 + 16 + -1 + <_> + + + <_> + + <_> + + + + <_>4 3 11 9 -1. + <_>4 6 11 3 3. + 0 + -0.0986907333135605 + 1 + 0.3999474942684174 + <_> + + + + <_>0 2 6 11 -1. + <_>3 2 3 11 2. + 0 + 0.0623734183609486 + 0.5247784852981567 + 0.8193575739860535 + <_> + + <_> + + + + <_>13 0 4 5 -1. + <_>13 0 2 5 2. + 0 + 1.9496519817039371e-003 + 0.3529816865921021 + 1 + <_> + + + + <_>9 7 6 4 -1. + <_>12 7 3 2 2. + <_>9 9 3 2 2. + 0 + -8.9139147894456983e-004 + 0.5852727890014648 + 0.3245978057384491 + <_> + + <_> + + + + <_>5 7 8 2 -1. + <_>9 7 4 2 2. + 0 + -5.5150408297777176e-004 + 0.3892816901206970 + 1 + <_> + + + + <_>1 8 15 1 -1. + <_>6 8 5 1 3. + 0 + -1.1721949558705091e-003 + 0.4335052073001862 + 0.6520624160766602 + <_> + + <_> + + + + <_>4 12 12 2 -1. + <_>8 12 4 2 3. + 0 + -7.4480642797425389e-004 + 1 + 0.4041135013103485 + <_> + + + + <_>13 0 4 10 -1. + <_>15 0 2 5 2. + <_>13 5 2 5 2. + 0 + -2.6264840271323919e-003 + 0.5624982118606567 + 0.3967525064945221 + <_> + + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + -3.9712688885629177e-004 + 0.3856112062931061 + 1 + <_> + + + + <_>3 9 6 2 -1. + <_>6 9 3 2 2. + 0 + 3.5984949208796024e-003 + 0.5997889041900635 + 0.4241614043712616 + <_> + + <_> + + + + <_>8 17 4 3 -1. + <_>8 18 4 1 3. + 0 + 5.3080618381500244e-003 + 1 + 0.6660168766975403 + <_> + + + + <_>8 3 9 2 -1. + <_>11 3 3 2 3. + 0 + 9.6319877775385976e-004 + 0.4481379091739655 + 0.5583487749099731 + <_> + + <_> + + + + <_>3 3 9 2 -1. + <_>6 3 3 2 3. + 0 + 5.0776469288393855e-004 + 0.3535459041595459 + 1 + <_> + + + + <_>5 0 9 14 -1. + <_>8 0 3 14 3. + 0 + 3.6223160568624735e-003 + 0.3409807085990906 + 0.5420687794685364 + <_> + + <_> + + + + <_>7 3 7 10 -1. + <_>7 8 7 5 2. + 0 + -0.0620614103972912 + 0.1934083998203278 + 1 + <_> + + + + <_>4 8 13 3 -1. + <_>4 9 13 1 3. + 0 + 6.4387189922854304e-004 + 0.4083626866340637 + 0.5490221977233887 + <_> + + <_> + + + + <_>3 12 14 4 -1. + <_>3 12 7 2 2. + <_>10 14 7 2 2. + 0 + 0.0262399092316628 + 1 + 0.2285708039999008 + <_> + + + + <_>8 12 4 2 -1. + <_>8 13 4 1 2. + 0 + 8.1940297968685627e-004 + 0.4648667871952057 + 0.6017355918884277 + <_> + + <_> + + + + <_>6 10 9 8 -1. + <_>6 14 9 4 2. + 0 + 2.3833119485061616e-004 + 1 + 0.3598038852214813 + <_> + + + + <_>9 12 2 8 -1. + <_>9 16 2 4 2. + 0 + -1.5869759954512119e-003 + 0.4259651005268097 + 0.5476434826850891 + <_> + + <_> + + + + <_>8 12 3 3 -1. + <_>8 13 3 1 3. + 0 + -6.7263417877256870e-003 + 0.6507238149642944 + 1 + <_> + + + + <_>5 5 4 10 -1. + <_>7 5 2 10 2. + 0 + 0.0110061103478074 + 0.5149409770965576 + 0.3362984955310822 + <_> + + <_> + + + + <_>14 15 3 3 -1. + <_>14 16 3 1 3. + 0 + 7.1445819921791553e-003 + 1 + 0.2672930061817169 + <_> + + + + <_>4 6 13 3 -1. + <_>4 7 13 1 3. + 0 + -4.7233798541128635e-003 + 0.5652182102203369 + 0.4298144876956940 + <_> + + <_> + + + + <_>3 15 3 3 -1. + <_>3 16 3 1 3. + 0 + 9.8437406122684479e-003 + 1 + 0.1151885986328125 + <_> + + + + <_>3 9 4 2 -1. + <_>3 9 2 1 2. + <_>5 10 2 1 2. + 0 + 1.5124640412977897e-005 + 0.4373598098754883 + 0.5612128973007202 + <_> + + <_> + + + + <_>0 11 20 4 -1. + <_>10 11 10 2 2. + <_>0 13 10 2 2. + 0 + 0.0399088710546494 + 0.5204648971557617 + 1 + <_> + + + + <_>8 15 4 3 -1. + <_>8 16 4 1 3. + 0 + 5.3903679363429546e-003 + 0.4813467860221863 + 0.6361209154129028 + <_> + + <_> + + + + <_>0 11 20 4 -1. + <_>0 11 10 2 2. + <_>10 13 10 2 2. + 0 + -0.0399088710546494 + 0.1506870985031128 + 1 + <_> + + + + <_>8 15 4 3 -1. + <_>8 16 4 1 3. + 0 + 5.3903679363429546e-003 + 0.4581694900989533 + 0.6200240850448608 + <_> + + <_> + + + + <_>10 13 1 6 -1. + <_>10 16 1 3 2. + 0 + 6.7005190066993237e-003 + 1 + 0.3432235121726990 + <_> + + + + <_>2 1 18 2 -1. + <_>11 1 9 1 2. + <_>2 2 9 1 2. + 0 + -0.0126237897202373 + 0.3088226914405823 + 0.5226737856864929 + <_> + + <_> + + + + <_>8 14 3 3 -1. + <_>8 15 3 1 3. + 0 + 0.0118066100403667 + 1 + 0.7187939286231995 + <_> + + + + <_>4 1 6 1 -1. + <_>6 1 2 1 3. + 0 + -3.4257229417562485e-003 + 0.3120814859867096 + 0.5065844058990479 + <_> + + <_> + + + + <_>11 13 1 3 -1. + <_>11 14 1 1 3. + 0 + 3.9385299896821380e-004 + 0.4754584133625031 + 1 + <_> + + + + <_>13 5 2 12 -1. + <_>13 11 2 6 2. + 0 + 0.0343881882727146 + 0.5261657834053040 + 0.3350174129009247 + <_> + + <_> + + + + <_>1 14 18 6 -1. + <_>1 16 18 2 3. + 0 + -0.0750099867582321 + 0.1713480949401856 + 1 + <_> + + + + <_>8 13 1 3 -1. + <_>8 14 1 1 3. + 0 + 4.9022492021322250e-004 + 0.4725801944732666 + 0.5956469178199768 + <_> + + <_> + + + + <_>7 13 6 3 -1. + <_>7 14 6 1 3. + 0 + -8.5525289177894592e-003 + 0.6558222770690918 + 1 + <_> + + + + <_>9 10 3 2 -1. + <_>9 11 3 1 2. + 0 + 1.3135520566720515e-004 + 0.4835400879383087 + 0.5586913824081421 + <_> + + <_> + + + + <_>5 1 3 3 -1. + <_>6 1 1 3 3. + 0 + 4.7948658466339111e-003 + 1 + 0.2645705938339233 + <_> + + + + <_>5 5 6 5 -1. + <_>8 5 3 5 2. + 0 + 2.0124691072851419e-003 + 0.3657945096492767 + 0.5124772191047669 + <_> + + <_> + + + + <_>7 5 6 14 -1. + <_>7 12 6 7 2. + 0 + -0.1178547963500023 + 0.2385654002428055 + 1 + <_> + + + + <_>7 16 6 2 -1. + <_>9 16 2 2 3. + 0 + 1.5575019642710686e-003 + 0.5490474104881287 + 0.4274747967720032 + <_> + + <_> + + + + <_>0 2 2 12 -1. + <_>1 2 1 12 2. + 0 + -0.0155737595632672 + 0.6938900947570801 + 1 + <_> + + + + <_>1 0 5 3 -1. + <_>1 1 5 1 3. + 0 + -2.1854790393263102e-003 + 0.3645988106727600 + 0.5092526078224182 + <_> + + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + 2.9272339306771755e-003 + 0.4685808122158051 + 1 + <_> + + + + <_>12 6 3 3 -1. + <_>12 7 3 1 3. + 0 + 6.4663668163120747e-003 + 0.4973410069942474 + 0.7726097106933594 + <_> + + <_> + + + + <_>5 4 3 3 -1. + <_>5 5 3 1 3. + 0 + -7.6140360906720161e-003 + 0.6877465844154358 + 1 + <_> + + + + <_>5 6 3 3 -1. + <_>5 7 3 1 3. + 0 + 4.1512572206556797e-003 + 0.4788525104522705 + 0.6921657919883728 + <_> + + <_> + + + + <_>8 12 4 8 -1. + <_>10 12 2 4 2. + <_>8 16 2 4 2. + 0 + 2.7711640577763319e-003 + 0.5481839776039124 + 1 + <_> + + + + <_>2 17 18 2 -1. + <_>11 17 9 1 2. + <_>2 18 9 1 2. + 0 + -0.0128361098468304 + 0.3800162971019745 + 0.5204492807388306 + <_> + + <_> + + + + <_>9 3 2 2 -1. + <_>9 4 2 1 2. + 0 + -2.4380050599575043e-003 + 0.2582435011863709 + 1 + <_> + + + + <_>8 5 4 6 -1. + <_>8 7 4 2 3. + 0 + 2.1713329479098320e-003 + 0.4961163103580475 + 0.3215202987194061 + <_> + + <_> + + + + <_>9 0 8 6 -1. + <_>9 2 8 2 3. + 0 + 6.2800728483125567e-004 + 1 + 0.5460423827171326 + <_> + + + + <_>1 0 18 4 -1. + <_>7 0 6 4 3. + 0 + -9.7982389852404594e-003 + 0.6046543717384338 + 0.4939922094345093 + <_> + + <_> + + + + <_>0 0 4 8 -1. + <_>2 0 2 8 2. + 0 + 7.3543828912079334e-003 + 1 + 0.5291094183921814 + <_> + + + + <_>0 4 6 9 -1. + <_>2 4 2 9 3. + 0 + -0.0146650401875377 + 0.5446122884750366 + 0.3567362129688263 + <_> + + <_> + + + + <_>1 4 18 2 -1. + <_>7 4 6 2 3. + 0 + 0.0302445106208324 + 0.5518329143524170 + 1 + <_> + + + + <_>8 16 12 4 -1. + <_>14 16 6 2 2. + <_>8 18 6 2 2. + 0 + -0.0566602088510990 + 0.6930978894233704 + 0.5093387961387634 + <_> + + <_> + + + + <_>0 0 18 2 -1. + <_>0 0 9 1 2. + <_>9 1 9 1 2. + 0 + -5.6967479176819324e-003 + 0.3201526105403900 + 1 + <_> + + + + <_>3 0 3 18 -1. + <_>4 0 1 18 3. + 0 + 0.0308067705482244 + 0.4989246129989624 + 0.2277054041624069 + <_> + + <_> + + + + <_>14 9 4 7 -1. + <_>14 9 2 7 2. + 0 + 2.2748769260942936e-003 + 0.4810931086540222 + 1 + <_> + + + + <_>15 14 2 2 -1. + <_>15 15 2 1 2. + 0 + 2.0436900667846203e-003 + 0.5283867120742798 + 0.3255924880504608 + <_> + + <_> + + + + <_>2 9 4 7 -1. + <_>4 9 2 7 2. + 0 + -8.6277956143021584e-003 + 0.6266536116600037 + 1 + <_> + + + + <_>3 14 2 2 -1. + <_>3 15 2 1 2. + 0 + 6.5113382879644632e-004 + 0.5097137093544006 + 0.3191910088062286 + <_> + + <_> + + + + <_>11 0 6 6 -1. + <_>11 2 6 2 3. + 0 + 8.8188261725008488e-004 + 0.4549585878849030 + 1 + <_> + + + + <_>14 0 2 6 -1. + <_>15 0 1 3 2. + <_>14 3 1 3 2. + 0 + -0.0145949097350240 + 0.2645038962364197 + 0.5153868198394775 + <_> + + <_> + + + + <_>7 11 2 2 -1. + <_>7 11 1 1 2. + <_>8 12 1 1 2. + 0 + -1.2304580304771662e-003 + 0.6197584867477417 + 1 + <_> + + + + <_>7 10 2 2 -1. + <_>8 10 1 2 2. + 0 + -2.1867299801670015e-004 + 0.5469198822975159 + 0.4206855893135071 + <_> + + <_> + + + + <_>9 14 2 6 -1. + <_>9 17 2 3 2. + 0 + -1.0909959673881531e-003 + 0.4140760004520416 + 1 + <_> + + + + <_>12 18 4 2 -1. + <_>12 19 4 1 2. + 0 + 3.5210378700867295e-004 + 0.5476608872413635 + 0.4155021011829376 + <_> + + <_> + + + + <_>8 17 4 3 -1. + <_>8 18 4 1 3. + 0 + -7.2563779540359974e-003 + 0.7160469293594360 + 1 + <_> + + + + <_>2 18 8 2 -1. + <_>2 19 8 1 2. + 0 + 1.4701850013807416e-003 + 0.5240808129310608 + 0.3729662895202637 + <_> + + <_> + + + + <_>2 9 16 3 -1. + <_>2 10 16 1 3. + 0 + 1.1472719779703766e-004 + 0.4033798873424530 + 1 + <_> + + + + <_>9 9 2 2 -1. + <_>9 10 2 1 2. + 0 + 3.0506469774991274e-003 + 0.5263985991477966 + 0.3560093045234680 + <_> + + <_> + + + + <_>5 14 2 4 -1. + <_>5 14 1 2 2. + <_>6 16 1 2 2. + 0 + 2.6269949739798903e-004 + 0.4569799900054932 + 1 + <_> + + + + <_>8 9 4 2 -1. + <_>8 9 2 1 2. + <_>10 10 2 1 2. + 0 + -3.6365550477057695e-003 + 0.3042570948600769 + 0.5868253707885742 + <_> + + <_> + + + + <_>9 5 2 5 -1. + <_>9 5 1 5 2. + 0 + -8.4893293678760529e-003 + 1 + 0.4914157092571259 + <_> + + + + <_>9 9 3 2 -1. + <_>10 9 1 2 3. + 0 + 5.8107408694922924e-003 + 0.4918529987335205 + 0.6266962885856628 + <_> + + <_> + + + + <_>8 9 3 2 -1. + <_>9 9 1 2 3. + 0 + 7.5583951547741890e-004 + 1 + 0.5633236169815064 + <_> + + + + <_>8 8 3 6 -1. + <_>9 8 1 6 3. + 0 + -2.2017690353095531e-003 + 0.5553916096687317 + 0.3827646076679230 + <_> + + <_> + + + + <_>8 12 4 8 -1. + <_>10 12 2 4 2. + <_>8 16 2 4 2. + 0 + 2.7908938936889172e-003 + 0.5498697757720947 + 1 + <_> + + + + <_>2 17 16 2 -1. + <_>10 17 8 1 2. + <_>2 18 8 1 2. + 0 + -1.8228569533675909e-003 + 0.4382283091545105 + 0.5424032807350159 + <_> + + <_> + + + + <_>8 12 3 8 -1. + <_>9 12 1 8 3. + 0 + -7.2495508939027786e-003 + 0.2888121902942658 + 1 + <_> + + + + <_>3 10 1 3 -1. + <_>3 11 1 1 3. + 0 + -6.8744522286579013e-004 + 0.3472655117511749 + 0.5076370835304260 + <_> + + <_> + + + + <_>9 14 10 6 -1. + <_>14 14 5 3 2. + <_>9 17 5 3 2. + 0 + 2.5174440816044807e-003 + 0.4661205112934113 + 1 + <_> + + + + <_>14 13 3 6 -1. + <_>14 15 3 2 3. + 0 + -0.0101513797417283 + 0.3744775056838989 + 0.5294001102447510 + <_> + + <_> + + + + <_>1 19 18 1 -1. + <_>7 19 6 1 3. + 0 + -4.1399952024221420e-003 + 1 + 0.4660485088825226 + <_> + + + + <_>2 10 15 2 -1. + <_>7 10 5 2 3. + 0 + -4.7078551724553108e-003 + 0.4175061881542206 + 0.6916306018829346 + <_> + + <_> + + + + <_>4 17 16 3 -1. + <_>4 18 16 1 3. + 0 + 0.0419810414314270 + 1 + 0.2018215060234070 + <_> + + + + <_>8 6 4 9 -1. + <_>8 9 4 3 3. + 0 + -0.0142729999497533 + 0.7511197924613953 + 0.5032083988189697 + <_> + + <_> + + + + <_>9 16 2 4 -1. + <_>9 16 1 2 2. + <_>10 18 1 2 2. + 0 + 4.0869521908462048e-003 + 1 + 0.2504513859748840 + <_> + + + + <_>5 5 10 8 -1. + <_>5 9 10 4 2. + 0 + 1.7606799956411123e-003 + 0.3301401138305664 + 0.5218337178230286 + <_> + + <_> + + + + <_>13 1 4 2 -1. + <_>13 1 2 2 2. + 0 + 1.2550549581646919e-004 + 0.4614442884922028 + 1 + <_> + + + + <_>14 0 3 6 -1. + <_>14 2 3 2 3. + 0 + -2.9503209516406059e-003 + 0.4619950056076050 + 0.5247030258178711 + <_> + + <_> + + + + <_>6 7 2 2 -1. + <_>6 7 1 1 2. + <_>7 8 1 1 2. + 0 + -1.1312420247122645e-003 + 0.6314368247985840 + 1 + <_> + + + + <_>7 1 6 1 -1. + <_>9 1 2 1 3. + 0 + -1.6983180539682508e-003 + 0.3401306867599487 + 0.5055527091026306 + <_> + + <_> + + + + <_>9 11 3 3 -1. + <_>9 12 3 1 3. + 0 + -0.0114578204229474 + 1 + 0.4939996004104614 + <_> + + + + <_>12 9 3 3 -1. + <_>13 9 1 3 3. + 0 + -8.4962565451860428e-003 + 0.2965450882911682 + 0.5194367766380310 + <_> + + <_> + + + + <_>8 11 3 3 -1. + <_>8 12 3 1 3. + 0 + 0.0119190895929933 + 1 + 0.7886998057365418 + <_> + + + + <_>5 9 3 3 -1. + <_>6 9 1 3 3. + 0 + 6.4416420646011829e-003 + 0.5106986761093140 + 0.2967146039009094 + <_> + + <_> + + + + <_>10 11 1 3 -1. + <_>10 12 1 1 3. + 0 + -8.7857811013236642e-004 + 0.5714371204376221 + 1 + <_> + + + + <_>7 9 6 4 -1. + <_>10 9 3 2 2. + <_>7 11 3 2 2. + 0 + -2.0312711130827665e-003 + 0.4481200873851776 + 0.5384911894798279 + <_> + + <_> + + + + <_>4 7 2 2 -1. + <_>4 7 1 1 2. + <_>5 8 1 1 2. + 0 + -1.5262430533766747e-003 + 0.6193568706512451 + 1 + <_> + + + + <_>5 7 3 1 -1. + <_>6 7 1 1 3. + 0 + 4.2860880494117737e-003 + 0.4339885115623474 + 0.7697299122810364 + <_> + + <_> + + + + <_>18 3 2 3 -1. + <_>18 4 2 1 3. + 0 + 3.5010920837521553e-003 + 1 + 0.3171389102935791 + <_> + + + + <_>13 1 4 2 -1. + <_>13 1 2 2 2. + 0 + 0.0125876702368259 + 0.5246698856353760 + 0.4241208136081696 + <_> + + <_> + + + + <_>3 1 4 2 -1. + <_>5 1 2 2 2. + 0 + 2.6207490009255707e-004 + 0.4231899976730347 + 1 + <_> + + + + <_>3 0 5 2 -1. + <_>3 1 5 1 2. + 0 + 4.4701730075757951e-005 + 0.4174138903617859 + 0.5919603705406189 + <_> + + <_> + + + + <_>14 7 6 4 -1. + <_>17 7 3 2 2. + <_>14 9 3 2 2. + 0 + 7.8084698179736733e-004 + 0.4277389049530029 + 1 + <_> + + + + <_>4 8 16 2 -1. + <_>4 9 16 1 2. + 0 + 8.8851212058216333e-004 + 0.3720161020755768 + 0.5226818919181824 + <_> + + <_> + + + + <_>2 11 5 6 -1. + <_>2 13 5 2 3. + 0 + 2.3369069676846266e-003 + 0.5478066802024841 + 1 + <_> + + + + <_>5 16 2 4 -1. + <_>5 16 1 2 2. + <_>6 18 1 2 2. + 0 + 1.6688359901309013e-003 + 0.3628678917884827 + 0.6150004863739014 + <_> + + <_> + + + + <_>15 6 2 12 -1. + <_>16 6 1 6 2. + <_>15 12 1 6 2. + 0 + 3.0844469438306987e-004 + 0.4747075140476227 + 1 + <_> + + + + <_>13 3 6 16 -1. + <_>15 3 2 16 3. + 0 + 3.4617560449987650e-003 + 0.4580138027667999 + 0.5585681796073914 + <_> + + <_> + + + + <_>4 5 12 12 -1. + <_>4 5 6 6 2. + <_>10 11 6 6 2. + 0 + 0.0189613103866577 + 0.5298801064491272 + 1 + <_> + + + + <_>5 1 10 13 -1. + <_>10 1 5 13 2. + 0 + 0.1734731048345566 + 0.3698385059833527 + 0.8498619794845581 + <_> + + <_> + + + + <_>11 5 2 2 -1. + <_>12 5 1 1 2. + <_>11 6 1 1 2. + 0 + 2.0020549709443003e-004 + 1 + 0.5565661787986755 + <_> + + + + <_>13 5 1 3 -1. + <_>13 6 1 1 3. + 0 + 1.0967060225084424e-003 + 0.4795713126659393 + 0.6286259889602661 + <_> + + <_> + + + + <_>7 4 2 4 -1. + <_>7 4 1 2 2. + <_>8 6 1 2 2. + 0 + 1.5107099898159504e-004 + 0.4052405953407288 + 1 + <_> + + + + <_>7 5 6 4 -1. + <_>10 5 3 4 2. + 0 + -3.4463501069694757e-003 + 0.6173015236854553 + 0.4414263963699341 + <_> + + <_> + + + + <_>12 4 4 6 -1. + <_>14 4 2 3 2. + <_>12 7 2 3 2. + 0 + 8.5176620632410049e-003 + 1 + 0.3570570945739746 + <_> + + + + <_>12 11 7 6 -1. + <_>12 13 7 2 3. + 0 + -0.0358121097087860 + 0.3151328861713409 + 0.5252702832221985 + <_> + + <_> + + + + <_>5 6 6 6 -1. + <_>7 6 2 6 3. + 0 + -0.0211554002016783 + 0.6124721169471741 + 1 + <_> + + + + <_>9 8 2 2 -1. + <_>9 9 2 1 2. + 0 + 8.9890940580517054e-004 + 0.5169975757598877 + 0.3596271872520447 + <_> + + <_> + + + + <_>15 6 2 2 -1. + <_>16 6 1 1 2. + <_>15 7 1 1 2. + 0 + -1.5613760333508253e-003 + 1 + 0.4914987981319428 + <_> + + + + <_>14 7 4 4 -1. + <_>16 7 2 2 2. + <_>14 9 2 2 2. + 0 + 6.7120860330760479e-004 + 0.4546211063861847 + 0.5395811796188355 + <_> + + <_> + + + + <_>5 5 6 2 -1. + <_>7 5 2 2 3. + 0 + -0.0215970296412706 + 0.1903133988380432 + 1 + <_> + + + + <_>1 19 18 1 -1. + <_>7 19 6 1 3. + 0 + -0.0249472297728062 + 0.6974077224731445 + 0.4967716038227081 + <_> + + <_> + + + + <_>12 3 3 3 -1. + <_>12 4 3 1 3. + 0 + 1.8725979607552290e-003 + 0.4748947918415070 + 1 + <_> + + + + <_>16 0 2 3 -1. + <_>16 1 2 1 3. + 0 + 6.3912719488143921e-003 + 0.5180178284645081 + 0.2924321889877319 + <_> + + <_> + + + + <_>5 3 3 3 -1. + <_>5 4 3 1 3. + 0 + -9.1552399098873138e-003 + 0.7665870189666748 + 1 + <_> + + + + <_>2 0 2 3 -1. + <_>2 1 2 1 3. + 0 + 2.1715660113841295e-003 + 0.5215551257133484 + 0.3365719020366669 + <_> + + <_> + + + + <_>15 6 2 2 -1. + <_>16 6 1 1 2. + <_>15 7 1 1 2. + 0 + 1.2330369791015983e-003 + 1 + 0.6260957717895508 + <_> + + + + <_>10 13 1 6 -1. + <_>10 16 1 3 2. + 0 + -4.0785901364870369e-004 + 0.4533509910106659 + 0.5386489033699036 + <_> + + <_> + + + + <_>0 7 10 2 -1. + <_>0 7 5 1 2. + <_>5 8 5 1 2. + 0 + 4.6437609125860035e-004 + 0.4103496074676514 + 1 + <_> + + + + <_>3 10 6 2 -1. + <_>3 11 6 1 2. + 0 + -1.1600199650274590e-004 + 0.5830391049385071 + 0.4304105937480927 + <_> + + <_> + + + + <_>12 18 4 2 -1. + <_>12 19 4 1 2. + 0 + -0.0127187203615904 + 0.2132582962512970 + 1 + <_> + + + + <_>12 18 2 2 -1. + <_>13 18 1 1 2. + <_>12 19 1 1 2. + 0 + 8.9431880041956902e-005 + 0.4872891008853912 + 0.5458915233612061 + <_> + + <_> + + + + <_>6 19 2 1 -1. + <_>7 19 1 1 2. + 0 + -3.3913689549081028e-004 + 0.3974364995956421 + 1 + <_> + + + + <_>0 4 2 16 -1. + <_>0 4 1 8 2. + <_>1 12 1 8 2. + 0 + -0.0180263407528400 + 0.7568550705909729 + 0.5045611858367920 + <_> + + <_> + + + + <_>16 1 4 9 -1. + <_>16 4 4 3 3. + 0 + 6.9179181009531021e-003 + 1 + 0.3966299891471863 + <_> + + + + <_>10 2 1 2 -1. + <_>10 3 1 1 2. + 0 + -1.1839679791592062e-004 + 0.4198082983493805 + 0.5435804128646851 + <_> + + <_> + + + + <_>4 14 4 6 -1. + <_>4 14 2 3 2. + <_>6 17 2 3 2. + 0 + -3.9474181830883026e-003 + 0.6369457840919495 + 1 + <_> + + + + <_>4 15 1 4 -1. + <_>4 17 1 2 2. + 0 + 6.0050919273635373e-005 + 0.5269566774368286 + 0.3812243044376373 + <_> + + <_> + + + + <_>0 2 20 4 -1. + <_>10 2 10 2 2. + <_>0 4 10 2 2. + 0 + 9.1423643752932549e-003 + 1 + 0.4156762957572937 + <_> + + + + <_>14 5 2 8 -1. + <_>14 9 2 4 2. + 0 + 2.1305440168362111e-004 + 0.3523533046245575 + 0.5349454283714294 + <_> + + <_> + + + + <_>5 12 4 5 -1. + <_>7 12 2 5 2. + 0 + -2.0855850016232580e-004 + 1 + 0.4403322041034699 + <_> + + + + <_>0 13 9 6 -1. + <_>0 15 9 2 3. + 0 + 1.3130389852449298e-003 + 0.6058161258697510 + 0.4468218982219696 + <_> + + <_> + + + + <_>9 14 11 3 -1. + <_>9 15 11 1 3. + 0 + -2.9134768992662430e-003 + 1 + 0.4825705885887146 + <_> + + + + <_>7 14 7 3 -1. + <_>7 15 7 1 3. + 0 + 2.9645769391208887e-003 + 0.4835998117923737 + 0.6039277911186218 + <_> + + <_> + + + + <_>3 6 2 2 -1. + <_>3 6 1 1 2. + <_>4 7 1 1 2. + 0 + 1.7772549763321877e-003 + 1 + 0.6871827244758606 + <_> + + + + <_>6 7 2 7 -1. + <_>7 7 1 7 2. + 0 + -7.7136349864304066e-003 + 0.2842220962047577 + 0.5145428180694580 + <_> + + <_> + + + + <_>14 5 1 3 -1. + <_>14 6 1 1 3. + 0 + 5.1027478184551001e-004 + 1 + 0.6024426221847534 + <_> + + + + <_>13 4 4 3 -1. + <_>13 5 4 1 3. + 0 + 1.7460630042478442e-003 + 0.4756610095500946 + 0.5721154212951660 + <_> + + <_> + + + + <_>2 7 4 4 -1. + <_>2 7 2 2 2. + <_>4 9 2 2 2. + 0 + 3.8068278809078038e-004 + 1 + 0.4931069016456604 + <_> + + + + <_>2 9 13 6 -1. + <_>2 12 13 3 2. + 0 + 2.8228890150785446e-003 + 0.3311698138713837 + 0.6227598190307617 + <_> + + <_> + + + + <_>10 1 3 4 -1. + <_>11 1 1 4 3. + 0 + -5.3000478073954582e-003 + 1 + 0.5232092738151550 + <_> + + + + <_>9 8 5 2 -1. + <_>9 9 5 1 2. + 0 + 4.4951299059903249e-005 + 0.3995231986045837 + 0.5314797759056091 + <_> + + <_> + + + + <_>0 14 11 3 -1. + <_>0 15 11 1 3. + 0 + 3.2752458937466145e-003 + 0.4481619894504547 + 1 + <_> + + + + <_>8 11 2 8 -1. + <_>8 15 2 4 2. + 0 + -2.8162579983472824e-003 + 0.3907971978187561 + 0.6671640872955322 + <_> + + <_> + + + + <_>5 11 10 6 -1. + <_>5 14 10 3 2. + 0 + 1.4112279750406742e-003 + 0.5357010960578919 + 1 + <_> + + + + <_>5 13 15 5 -1. + <_>10 13 5 5 3. + 0 + 8.3062034100294113e-003 + 0.4770965874195099 + 0.5570099949836731 + <_> + + <_> + + + + <_>8 10 1 10 -1. + <_>8 15 1 5 2. + 0 + 2.2164839319884777e-003 + 0.4947124123573303 + 1 + <_> + + + + <_>4 14 6 2 -1. + <_>6 14 2 2 3. + 0 + -4.9868631176650524e-003 + 0.5241307020187378 + 0.2512654960155487 + <_> + + <_> + + + + <_>7 14 7 3 -1. + <_>7 15 7 1 3. + 0 + -3.6664260551333427e-003 + 1 + 0.4619553983211517 + <_> + + + + <_>7 16 9 3 -1. + <_>7 17 9 1 3. + 0 + -0.0105812298133969 + 0.6301718950271606 + 0.4973031878471375 + <_> + + <_> + + + + <_>8 7 3 3 -1. + <_>8 8 3 1 3. + 0 + 7.3366491124033928e-003 + 1 + 0.2870970070362091 + <_> + + + + <_>3 5 1 6 -1. + <_>3 8 1 3 2. + 0 + -3.9318940252996981e-004 + 0.4252805113792419 + 0.5579246878623962 + <_> + + <_> + + + + <_>6 5 11 2 -1. + <_>6 6 11 1 2. + 0 + -8.1375334411859512e-003 + 0.5747315883636475 + 1 + <_> + + + + <_>9 0 3 2 -1. + <_>10 0 1 2 3. + 0 + 2.4809150490909815e-003 + 0.5203374028205872 + 0.3903566896915436 + <_> + + <_> + + + + <_>5 5 1 3 -1. + <_>5 6 1 1 3. + 0 + 8.8749779388308525e-004 + 1 + 0.5534321069717407 + <_> + + + + <_>8 7 3 2 -1. + <_>9 7 1 2 3. + 0 + -4.2194919660687447e-004 + 0.5338044166564941 + 0.3925840854644775 + <_> + + <_> + + + + <_>5 2 10 6 -1. + <_>10 2 5 3 2. + <_>5 5 5 3 2. + 0 + -7.9790111631155014e-003 + 0.4144316017627716 + 1 + <_> + + + + <_>8 4 6 4 -1. + <_>8 4 3 4 2. + 0 + 1.1439629597589374e-003 + 0.4701372981071472 + 0.5281736254692078 + <_> + + <_> + + + + <_>8 16 3 4 -1. + <_>9 16 1 4 3. + 0 + 7.5542130507528782e-003 + 1 + 0.2527256011962891 + <_> + + + + <_>9 13 2 6 -1. + <_>9 13 1 3 2. + <_>10 16 1 3 2. + 0 + 1.0288399644196033e-003 + 0.5605146288871765 + 0.4297856092453003 + <_> + + <_> + + + + <_>9 8 3 1 -1. + <_>10 8 1 1 3. + 0 + -1.7234670231118798e-003 + 1 + 0.4839682877063751 + <_> + + + + <_>2 5 18 15 -1. + <_>2 10 18 5 3. + 0 + 0.5758669972419739 + 0.5110502839088440 + 0.0804893299937248 + 44.2512817382812500 + 17 + -1 + <_> + + + <_> + + <_> + + + + <_>1 3 6 2 -1. + <_>4 3 3 2 2. + 0 + 6.6640521399676800e-003 + 0.3828920125961304 + 1 + <_> + + + + <_>7 6 6 2 -1. + <_>9 6 2 2 3. + 0 + 8.9905522763729095e-003 + 0.4858429133892059 + 0.7354959249496460 + <_> + + <_> + + + + <_>8 17 4 3 -1. + <_>8 18 4 1 3. + 0 + 5.7154200039803982e-003 + 1 + 0.6723223924636841 + <_> + + + + <_>10 13 2 3 -1. + <_>10 14 2 1 3. + 0 + 1.1257929727435112e-003 + 0.4429577887058258 + 0.6070777773857117 + <_> + + <_> + + + + <_>0 10 20 4 -1. + <_>0 12 20 2 2. + 0 + -9.1789010912179947e-004 + 1 + 0.3076345026493073 + <_> + + + + <_>5 7 6 4 -1. + <_>5 7 3 2 2. + <_>8 9 3 2 2. + 0 + -1.0492859873920679e-003 + 0.5593643784523010 + 0.3651022911071777 + <_> + + <_> + + + + <_>11 12 1 2 -1. + <_>11 13 1 1 2. + 0 + 3.5453929740469903e-005 + 0.4277968108654022 + 1 + <_> + + + + <_>10 10 2 3 -1. + <_>10 11 2 1 3. + 0 + 2.9015709878876805e-004 + 0.4583545029163361 + 0.5284683108329773 + <_> + + <_> + + + + <_>9 5 2 2 -1. + <_>9 6 2 1 2. + 0 + 1.6071660502348095e-004 + 1 + 0.3798192143440247 + <_> + + + + <_>4 4 1 10 -1. + <_>4 9 1 5 2. + 0 + -5.2961107576265931e-004 + 0.3850437104701996 + 0.5939688086509705 + <_> + + <_> + + + + <_>11 18 4 2 -1. + <_>11 18 2 2 2. + 0 + 2.6682569296099246e-004 + 0.4123024940490723 + 1 + <_> + + + + <_>12 18 3 2 -1. + <_>12 19 3 1 2. + 0 + -1.3492540165316314e-004 + 0.5760599970817566 + 0.4237645864486694 + <_> + + <_> + + + + <_>0 6 16 6 -1. + <_>0 6 8 3 2. + <_>8 9 8 3 2. + 0 + -0.0108416797593236 + 0.3929921090602875 + 1 + <_> + + + + <_>7 6 4 12 -1. + <_>7 12 4 6 2. + 0 + 0.0120778298005462 + 0.5761923193931580 + 0.2780444920063019 + <_> + + <_> + + + + <_>11 18 4 2 -1. + <_>11 18 2 2 2. + 0 + 2.2128869313746691e-003 + 0.4794507026672363 + 1 + <_> + + + + <_>12 18 3 2 -1. + <_>12 19 3 1 2. + 0 + -0.0152661902830005 + 0.0740558803081512 + 0.5153577923774719 + <_> + + <_> + + + + <_>8 12 1 2 -1. + <_>8 13 1 1 2. + 0 + 6.7929533543065190e-005 + 1 + 0.5858737826347351 + <_> + + + + <_>8 13 1 3 -1. + <_>8 14 1 1 3. + 0 + 1.7633590323384851e-004 + 0.3567610979080200 + 0.5598962903022766 + <_> + + <_> + + + + <_>11 18 4 2 -1. + <_>11 18 2 2 2. + 0 + 8.1311381654813886e-004 + 1 + 0.5346850752830505 + <_> + + + + <_>14 12 4 6 -1. + <_>14 12 2 6 2. + 0 + 3.2630451023578644e-003 + 0.4782536923885346 + 0.5456753969192505 + <_> + + <_> + + + + <_>6 0 3 4 -1. + <_>7 0 1 4 3. + 0 + -3.9503918960690498e-003 + 0.2831811904907227 + 1 + <_> + + + + <_>4 0 2 8 -1. + <_>4 0 1 4 2. + <_>5 4 1 4 2. + 0 + -3.9864578866399825e-004 + 0.5485215783119202 + 0.4159697890281677 + <_> + + <_> + + + + <_>11 17 9 3 -1. + <_>14 17 3 3 3. + 0 + -0.0114325201138854 + 0.5639101266860962 + 1 + <_> + + + + <_>16 2 4 5 -1. + <_>16 2 2 5 2. + 0 + 5.3339172154664993e-003 + 0.4596984088420868 + 0.5931242704391480 + <_> + + <_> + + + + <_>0 2 5 9 -1. + <_>0 5 5 3 3. + 0 + 8.3193257451057434e-003 + 1 + 0.3230620026588440 + <_> + + + + <_>7 2 3 2 -1. + <_>8 2 1 2 3. + 0 + -4.2479918920435011e-004 + 0.3795293867588043 + 0.5408611297607422 + <_> + + <_> + + + + <_>11 17 9 3 -1. + <_>14 17 3 3 3. + 0 + -0.1118943020701408 + 0.1132297962903976 + 1 + <_> + + + + <_>16 2 4 5 -1. + <_>16 2 2 5 2. + 0 + -7.5553781352937222e-003 + 0.6339370012283325 + 0.4838770925998688 + <_> + + <_> + + + + <_>0 17 9 3 -1. + <_>3 17 3 3 3. + 0 + -7.0337029173970222e-003 + 0.5665255188941956 + 1 + <_> + + + + <_>0 2 4 5 -1. + <_>2 2 2 5 2. + 0 + -0.0148336803540587 + 0.6751418113708496 + 0.4140945076942444 + <_> + + <_> + + + + <_>5 11 10 9 -1. + <_>5 14 10 3 3. + 0 + 8.7506724521517754e-003 + 1 + 0.3561258912086487 + <_> + + + + <_>9 6 3 3 -1. + <_>9 7 3 1 3. + 0 + 1.6645010327920318e-003 + 0.5347279906272888 + 0.3649779856204987 + <_> + + <_> + + + + <_>3 17 5 3 -1. + <_>3 18 5 1 3. + 0 + 9.4900820404291153e-003 + 1 + 0.2754656076431274 + <_> + + + + <_>7 5 4 7 -1. + <_>9 5 2 7 2. + 0 + 1.1133110383525491e-003 + 0.4225992858409882 + 0.5629178881645203 + <_> + + <_> + + + + <_>9 8 2 5 -1. + <_>9 8 1 5 2. + 0 + 9.4940755516290665e-003 + 0.4906036853790283 + 1 + <_> + + + + <_>2 2 18 2 -1. + <_>2 3 18 1 2. + 0 + -1.5396620146930218e-003 + 0.4007051885128021 + 0.5380709171295166 + <_> + + <_> + + + + <_>2 8 15 6 -1. + <_>7 8 5 6 3. + 0 + 0.1343495994806290 + 1 + 0.2214671969413757 + <_> + + + + <_>9 8 2 5 -1. + <_>10 8 1 5 2. + 0 + -9.4940755516290665e-003 + 0.7353156208992004 + 0.5005033016204834 + <_> + + <_> + + + + <_>12 10 4 6 -1. + <_>12 12 4 2 3. + 0 + 0.0200117900967598 + 1 + 0.3327906131744385 + <_> + + + + <_>14 3 6 2 -1. + <_>14 4 6 1 2. + 0 + -1.8875009845942259e-003 + 0.3915289044380188 + 0.5401849746704102 + <_> + + <_> + + + + <_>5 5 2 3 -1. + <_>5 6 2 1 3. + 0 + 7.1842782199382782e-003 + 1 + 0.7176604866981506 + <_> + + + + <_>4 6 3 3 -1. + <_>4 7 3 1 3. + 0 + 1.6976969782263041e-003 + 0.4526978135108948 + 0.6076912879943848 + <_> + + <_> + + + + <_>14 12 3 3 -1. + <_>14 13 3 1 3. + 0 + 4.9219978973269463e-003 + 1 + 0.2569833993911743 + <_> + + + + <_>6 12 11 3 -1. + <_>6 13 11 1 3. + 0 + 0.0118031995370984 + 0.4999637901782990 + 0.5958228111267090 + <_> + + <_> + + + + <_>1 2 3 6 -1. + <_>1 4 3 2 3. + 0 + -9.7703449428081512e-003 + 0.3459093868732452 + 1 + <_> + + + + <_>1 0 4 7 -1. + <_>3 0 2 7 2. + 0 + 2.1174899302423000e-003 + 0.4515126943588257 + 0.5829715728759766 + <_> + + <_> + + + + <_>9 8 3 4 -1. + <_>10 8 1 4 3. + 0 + 9.4801411032676697e-003 + 0.4807392060756683 + 1 + <_> + + + + <_>10 9 2 2 -1. + <_>10 10 2 1 2. + 0 + -2.6078789960592985e-003 + 0.3462216854095459 + 0.5201594829559326 + <_> + + <_> + + + + <_>8 8 3 4 -1. + <_>9 8 1 4 3. + 0 + -5.7252747938036919e-003 + 0.6599853038787842 + 1 + <_> + + + + <_>4 4 10 10 -1. + <_>4 9 10 5 2. + 0 + -8.2325618714094162e-003 + 0.2821828126907349 + 0.5125284790992737 + <_> + + <_> + + + + <_>9 10 3 2 -1. + <_>10 10 1 2 3. + 0 + 8.9571950957179070e-004 + 0.4883818924427033 + 1 + <_> + + + + <_>9 10 3 2 -1. + <_>9 11 3 1 2. + 0 + -1.5021569561213255e-004 + 0.4829918146133423 + 0.5428717136383057 + <_> + + <_> + + + + <_>8 10 3 2 -1. + <_>9 10 1 2 3. + 0 + 4.8489659093320370e-004 + 0.4434598982334137 + 1 + <_> + + + + <_>2 4 14 12 -1. + <_>2 4 7 6 2. + <_>9 10 7 6 2. + 0 + -0.0961926504969597 + 0.2256636023521423 + 0.5956227779388428 + <_> + + <_> + + + + <_>10 12 1 6 -1. + <_>10 15 1 3 2. + 0 + -1.1053519556298852e-003 + 0.4527224004268646 + 1 + <_> + + + + <_>7 3 8 16 -1. + <_>11 3 4 8 2. + <_>7 11 4 8 2. + 0 + -0.1021504029631615 + 0.2844349145889282 + 0.5186452865600586 + <_> + + <_> + + + + <_>5 6 8 10 -1. + <_>5 6 4 5 2. + <_>9 11 4 5 2. + 0 + 3.0147889629006386e-003 + 1 + 0.3808999061584473 + <_> + + + + <_>6 2 8 8 -1. + <_>6 2 4 4 2. + <_>10 6 4 4 2. + 0 + 7.6131648384034634e-003 + 0.5718699097633362 + 0.4262563884258270 + <_> + + <_> + + + + <_>10 5 4 2 -1. + <_>12 5 2 1 2. + <_>10 6 2 1 2. + 0 + 1.5197630273178220e-003 + 1 + 0.5942718982696533 + <_> + + + + <_>12 4 3 3 -1. + <_>12 5 3 1 3. + 0 + -0.0141972796991467 + 0.7731103897094727 + 0.4997653961181641 + <_> + + <_> + + + + <_>4 19 12 1 -1. + <_>8 19 4 1 3. + 0 + -0.0138188796117902 + 0.6681138277053833 + 1 + <_> + + + + <_>8 2 3 1 -1. + <_>9 2 1 1 3. + 0 + -5.0701329018920660e-004 + 0.3305608034133911 + 0.4749974906444550 + <_> + + <_> + + + + <_>13 17 4 3 -1. + <_>13 18 4 1 3. + 0 + -9.3537531793117523e-003 + 0.2860932946205139 + 1 + <_> + + + + <_>7 14 6 3 -1. + <_>7 15 6 1 3. + 0 + -9.4771059229969978e-003 + 0.6188883185386658 + 0.4842100143432617 + <_> + + <_> + + + + <_>9 14 2 3 -1. + <_>9 15 2 1 3. + 0 + 1.6923650400713086e-003 + 1 + 0.6070249080657959 + <_> + + + + <_>7 15 6 3 -1. + <_>7 16 6 1 3. + 0 + 5.8652542065829039e-004 + 0.3782689869403839 + 0.5368196964263916 + <_> + + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + -2.5826620403677225e-003 + 0.3690209984779358 + 1 + <_> + + + + <_>14 12 2 3 -1. + <_>14 13 2 1 3. + 0 + -2.7307639829814434e-003 + 0.3857114911079407 + 0.5318108797073364 + <_> + + <_> + + + + <_>4 10 4 6 -1. + <_>4 12 4 2 3. + 0 + 0.0218715704977512 + 1 + 0.2327008992433548 + <_> + + + + <_>4 13 3 2 -1. + <_>4 14 3 1 2. + 0 + -1.5010299648565706e-005 + 0.5560722947120667 + 0.4301410019397736 + <_> + + <_> + + + + <_>9 16 2 3 -1. + <_>9 17 2 1 3. + 0 + 5.3583700209856033e-003 + 1 + 0.6767637729644775 + <_> + + + + <_>10 18 3 2 -1. + <_>11 18 1 2 3. + 0 + 5.0057549960911274e-003 + 0.5194904208183289 + 0.3612853884696960 + <_> + + <_> + + + + <_>7 18 3 2 -1. + <_>8 18 1 2 3. + 0 + -1.9030070398002863e-003 + 0.3237845003604889 + 1 + <_> + + + + <_>1 10 4 2 -1. + <_>1 11 4 1 2. + 0 + -7.8506693243980408e-003 + 0.1194851994514465 + 0.4991723895072937 + <_> + + <_> + + + + <_>12 4 6 3 -1. + <_>12 5 6 1 3. + 0 + -2.7093670796602964e-003 + 1 + 0.4854960143566132 + <_> + + + + <_>14 4 1 3 -1. + <_>14 5 1 1 3. + 0 + 1.4138079714030027e-003 + 0.4872322976589203 + 0.5903577804565430 + <_> + + <_> + + + + <_>2 4 6 3 -1. + <_>2 5 6 1 3. + 0 + 9.0300198644399643e-003 + 1 + 0.6547315716743469 + <_> + + + + <_>5 4 1 3 -1. + <_>5 5 1 1 3. + 0 + -9.7925681620836258e-004 + 0.5849273204803467 + 0.4554230868816376 + <_> + + <_> + + + + <_>14 12 3 3 -1. + <_>14 13 3 1 3. + 0 + 1.3984439428895712e-003 + 1 + 0.4064626097679138 + <_> + + + + <_>15 12 2 3 -1. + <_>15 13 2 1 3. + 0 + 8.3372107474133372e-004 + 0.5399543046951294 + 0.4152809977531433 + <_> + + <_> + + + + <_>3 16 4 3 -1. + <_>3 17 4 1 3. + 0 + 0.0105510596185923 + 1 + 0.1796680986881256 + <_> + + + + <_>8 0 4 2 -1. + <_>8 1 4 1 2. + 0 + 8.8344102550763637e-005 + 0.4251863062381744 + 0.5413522720336914 + <_> + + <_> + + + + <_>0 0 20 1 -1. + <_>0 0 10 1 2. + 0 + -0.0410223081707954 + 1 + 0.5228124856948853 + <_> + + + + <_>9 7 3 4 -1. + <_>10 7 1 4 3. + 0 + 7.5065628625452518e-003 + 0.4853743016719818 + 0.6093444228172302 + <_> + + <_> + + + + <_>0 0 20 1 -1. + <_>10 0 10 1 2. + 0 + 0.0410223081707954 + 1 + 0.2205024063587189 + <_> + + + + <_>8 7 3 4 -1. + <_>9 7 1 4 3. + 0 + -5.3961377125233412e-004 + 0.5692731738090515 + 0.4468756914138794 + <_> + + <_> + + + + <_>1 6 19 3 -1. + <_>1 7 19 1 3. + 0 + -0.0686960369348526 + 0.1483314037322998 + 1 + <_> + + + + <_>12 7 4 2 -1. + <_>12 8 4 1 2. + 0 + -1.8447940237820148e-003 + 0.6211283802986145 + 0.4966601133346558 + <_> + + <_> + + + + <_>7 8 3 3 -1. + <_>7 9 3 1 3. + 0 + -6.0959919355809689e-003 + 0.2294671982526779 + 1 + <_> + + + + <_>7 7 3 3 -1. + <_>8 7 1 3 3. + 0 + -4.2068301700055599e-003 + 0.6407091021537781 + 0.4748562872409821 + <_> + + <_> + + + + <_>2 9 16 3 -1. + <_>2 10 16 1 3. + 0 + -7.1332789957523346e-004 + 1 + 0.5354936122894287 + <_> + + + + <_>9 4 2 12 -1. + <_>9 8 2 4 3. + 0 + 0.1175677999854088 + 0.5136978030204773 + 0.0105957398191094 + <_> + + <_> + + + + <_>7 3 2 5 -1. + <_>8 3 1 5 2. + 0 + 5.9354289987822995e-005 + 0.3711803853511810 + 1 + <_> + + + + <_>9 7 2 3 -1. + <_>9 8 2 1 3. + 0 + -6.3173691742122173e-003 + 0.1712073981761932 + 0.5061758160591126 + <_> + + <_> + + + + <_>9 14 4 3 -1. + <_>9 15 4 1 3. + 0 + 0.0149414995685220 + 1 + 0.6729118824005127 + <_> + + + + <_>7 8 6 4 -1. + <_>10 8 3 2 2. + <_>7 10 3 2 2. + 0 + -2.0789399277418852e-003 + 0.4410645961761475 + 0.5444027781486511 + <_> + + <_> + + + + <_>9 7 2 2 -1. + <_>10 7 1 2 2. + 0 + -7.0736219640821218e-004 + 0.5568910837173462 + 1 + <_> + + + + <_>5 5 6 6 -1. + <_>7 5 2 6 3. + 0 + -3.1247111037373543e-003 + 0.5023869276046753 + 0.3562405109405518 + <_> + + <_> + + + + <_>9 1 3 6 -1. + <_>10 1 1 6 3. + 0 + -7.8919378574937582e-004 + 1 + 0.5456786155700684 + <_> + + + + <_>4 5 12 2 -1. + <_>8 5 4 2 3. + 0 + 0.0101795801892877 + 0.5545138716697693 + 0.4622310996055603 + <_> + + <_> + + + + <_>4 2 6 4 -1. + <_>6 2 2 4 3. + 0 + -2.7506109327077866e-003 + 1 + 0.4942536056041718 + <_> + + + + <_>4 7 8 2 -1. + <_>4 8 8 1 2. + 0 + 0.0106013296172023 + 0.2961233854293823 + 0.5964338779449463 + <_> + + <_> + + + + <_>3 6 14 6 -1. + <_>10 6 7 3 2. + <_>3 9 7 3 2. + 0 + 5.1466780714690685e-003 + 0.5495228767395020 + 1 + <_> + + + + <_>3 6 14 3 -1. + <_>3 6 7 3 2. + 0 + 0.0763211473822594 + 0.5173959136009216 + 0.2940216958522797 + <_> + + <_> + + + + <_>0 5 2 2 -1. + <_>0 6 2 1 2. + 0 + -1.5027689514681697e-003 + 0.3106299936771393 + 1 + <_> + + + + <_>8 13 4 3 -1. + <_>8 14 4 1 3. + 0 + 0.0122666703537107 + 0.4651150107383728 + 0.6846613883972168 + <_> + + <_> + + + + <_>13 0 3 20 -1. + <_>14 0 1 20 3. + 0 + -0.0311185792088509 + 1 + 0.5226057171821594 + <_> + + + + <_>10 8 10 3 -1. + <_>10 9 10 1 3. + 0 + 0.0289055891335011 + 0.5182244181632996 + 0.2705428004264832 + <_> + + <_> + + + + <_>4 0 3 20 -1. + <_>5 0 1 20 3. + 0 + 0.0475983805954456 + 1 + 0.1109512001276016 + <_> + + + + <_>0 8 10 3 -1. + <_>0 9 10 1 3. + 0 + 0.0308085493743420 + 0.4938625097274780 + 0.1404110938310623 + <_> + + <_> + + + + <_>12 5 3 4 -1. + <_>13 5 1 4 3. + 0 + -2.1277810446918011e-004 + 1 + 0.4392356872558594 + <_> + + + + <_>6 7 12 4 -1. + <_>10 7 4 4 3. + 0 + 0.0789699628949165 + 0.5216552019119263 + 0.2294113934040070 + <_> + + <_> + + + + <_>1 14 6 6 -1. + <_>1 14 3 3 2. + <_>4 17 3 3 2. + 0 + -0.0102579500526190 + 0.6176652908325195 + 1 + <_> + + + + <_>1 17 6 2 -1. + <_>1 18 6 1 2. + 0 + 1.2604889925569296e-003 + 0.5236222743988037 + 0.3328965902328491 + <_> + + <_> + + + + <_>14 8 6 12 -1. + <_>17 8 3 6 2. + <_>14 14 3 6 2. + 0 + -0.0334904603660107 + 1 + 0.4866186976432800 + <_> + + + + <_>18 5 2 2 -1. + <_>18 6 2 1 2. + 0 + -5.9202767442911863e-004 + 0.4116407036781311 + 0.5395640134811401 + <_> + + <_> + + + + <_>3 16 4 2 -1. + <_>3 16 2 1 2. + <_>5 17 2 1 2. + 0 + 3.0320750738610514e-005 + 1 + 0.5610736012458801 + <_> + + + + <_>2 16 6 2 -1. + <_>4 16 2 2 3. + 0 + -5.4369680583477020e-004 + 0.5621389150619507 + 0.3461203873157501 + <_> + + <_> + + + + <_>14 8 6 12 -1. + <_>17 8 3 6 2. + <_>14 14 3 6 2. + 0 + -0.0334904603660107 + 1 + 0.4896762073040009 + <_> + + + + <_>18 5 2 2 -1. + <_>18 6 2 1 2. + 0 + -5.9202767442911863e-004 + 0.4305404126644135 + 0.5340713858604431 + <_> + + <_> + + + + <_>5 16 9 2 -1. + <_>8 16 3 2 3. + 0 + 2.0550889894366264e-003 + 0.5544999837875366 + 1 + <_> + + + + <_>3 14 6 6 -1. + <_>3 14 3 3 2. + <_>6 17 3 3 2. + 0 + -4.4353571720421314e-003 + 0.6038540005683899 + 0.3746592998504639 + <_> + + <_> + + + + <_>14 8 6 12 -1. + <_>17 8 3 6 2. + <_>14 14 3 6 2. + 0 + -0.0841704234480858 + 1 + 0.5007348060607910 + <_> + + + + <_>11 7 2 12 -1. + <_>11 11 2 4 3. + 0 + 6.7419027909636497e-003 + 0.5298097133636475 + 0.4716145098209381 + <_> + + <_> + + + + <_>0 8 6 12 -1. + <_>0 8 3 6 2. + <_>3 14 3 6 2. + 0 + 0.0102781504392624 + 1 + 0.6269375085830689 + <_> + + + + <_>7 7 2 12 -1. + <_>7 11 2 4 3. + 0 + 5.8800862170755863e-003 + 0.5154827833175659 + 0.3813040852546692 + <_> + + <_> + + + + <_>14 12 1 2 -1. + <_>14 13 1 1 2. + 0 + -6.9679190346505493e-006 + 1 + 0.4440239965915680 + <_> + + + + <_>12 13 8 1 -1. + <_>12 13 4 1 2. + 0 + 8.2419527461752295e-004 + 0.4697534143924713 + 0.5485504269599915 + <_> + + <_> + + + + <_>0 3 16 6 -1. + <_>0 6 16 3 2. + 0 + -5.5268318392336369e-003 + 0.5513604879379273 + 1 + <_> + + + + <_>1 4 8 2 -1. + <_>1 4 4 1 2. + <_>5 5 4 1 2. + 0 + 9.6128671430051327e-004 + 0.3618639111518860 + 0.5838456749916077 + <_> + + <_> + + + + <_>14 12 1 2 -1. + <_>14 13 1 1 2. + 0 + 2.4810510221868753e-003 + 1 + 0.2523222863674164 + <_> + + + + <_>15 12 2 3 -1. + <_>15 13 2 1 3. + 0 + -1.0480589699000120e-003 + 0.4117257893085480 + 0.5392996072769165 + <_> + + <_> + + + + <_>8 16 3 3 -1. + <_>8 17 3 1 3. + 0 + -6.1287907883524895e-003 + 0.6726329922676086 + 1 + <_> + + + + <_>5 12 1 2 -1. + <_>5 13 1 1 2. + 0 + 1.1682329932227731e-004 + 0.5041192770004273 + 0.3607729077339172 + <_> + + <_> + + + + <_>13 4 3 15 -1. + <_>14 4 1 15 3. + 0 + -0.0399094782769680 + 0.1563739031553268 + 1 + <_> + + + + <_>17 3 2 6 -1. + <_>18 3 1 3 2. + <_>17 6 1 3 2. + 0 + 1.5859459526836872e-003 + 0.4891980886459351 + 0.5779845118522644 + <_> + + <_> + + + + <_>4 4 3 15 -1. + <_>5 4 1 15 3. + 0 + -0.0226902291178703 + 0.2186879068613052 + 1 + <_> + + + + <_>1 3 2 6 -1. + <_>1 3 1 3 2. + <_>2 6 1 3 2. + 0 + 2.0916070789098740e-003 + 0.4771577119827271 + 0.6099231243133545 + <_> + + <_> + + + + <_>7 15 12 4 -1. + <_>7 17 12 2 2. + 0 + -0.0247154198586941 + 0.3463996946811676 + 1 + <_> + + + + <_>1 0 19 3 -1. + <_>1 1 19 1 3. + 0 + -0.0134194502606988 + 0.3630692958831787 + 0.5252196192741394 + <_> + + <_> + + + + <_>3 17 10 2 -1. + <_>3 17 5 1 2. + <_>8 18 5 1 2. + 0 + -6.0629472136497498e-003 + 0.6666321754455566 + 1 + <_> + + + + <_>2 5 10 15 -1. + <_>2 10 10 5 3. + 0 + -2.0921030081808567e-003 + 0.3399547040462494 + 0.5035697817802429 + <_> + + <_> + + + + <_>13 8 3 4 -1. + <_>13 10 3 2 2. + 0 + 0.0259618591517210 + 0.5036802887916565 + 1 + <_> + + + + <_>19 13 1 2 -1. + <_>19 14 1 1 2. + 0 + 1.7908669542521238e-004 + 0.5418530702590942 + 0.4318976998329163 + <_> + + <_> + + + + <_>4 8 3 4 -1. + <_>4 10 3 2 2. + 0 + -3.1546850223094225e-003 + 0.7221025228500366 + 1 + <_> + + + + <_>0 13 1 2 -1. + <_>0 14 1 1 2. + 0 + -1.1397759662941098e-003 + 0.3320972919464111 + 0.5024433732032776 + <_> + + <_> + + + + <_>12 7 2 12 -1. + <_>12 13 2 6 2. + 0 + -0.0478402115404606 + 0.1938765048980713 + 1 + <_> + + + + <_>14 7 2 2 -1. + <_>15 7 1 1 2. + <_>14 8 1 1 2. + 0 + 4.1577088995836675e-004 + 0.4802188873291016 + 0.5730714797973633 + <_> + + <_> + + + + <_>5 3 8 2 -1. + <_>5 4 8 1 2. + 0 + -4.4247039477340877e-004 + 0.4262515008449554 + 1 + <_> + + + + <_>0 2 2 6 -1. + <_>0 4 2 2 3. + 0 + 1.4479350065812469e-003 + 0.5719171166419983 + 0.4064153134822846 + <_> + + <_> + + + + <_>18 2 2 12 -1. + <_>19 2 1 6 2. + <_>18 8 1 6 2. + 0 + 0.0157015100121498 + 0.4995726048946381 + 1 + <_> + + + + <_>18 1 1 2 -1. + <_>18 2 1 1 2. + 0 + 2.7805729769170284e-004 + 0.5289286971092224 + 0.4581728875637054 + <_> + + <_> + + + + <_>0 2 2 12 -1. + <_>0 2 1 6 2. + <_>1 8 1 6 2. + 0 + -2.9010509606450796e-003 + 0.6012148261070252 + 1 + <_> + + + + <_>1 1 1 2 -1. + <_>1 2 1 1 2. + 0 + 2.0830519497394562e-004 + 0.5057976841926575 + 0.3599432110786438 + <_> + + <_> + + + + <_>16 4 4 14 -1. + <_>18 4 2 7 2. + <_>16 11 2 7 2. + 0 + -0.0515300296247005 + 1 + 0.4991796910762787 + <_> + + + + <_>10 14 1 6 -1. + <_>10 17 1 3 2. + 0 + 1.7163449956569821e-004 + 0.4675469994544983 + 0.5374773144721985 + <_> + + <_> + + + + <_>0 4 4 14 -1. + <_>0 4 2 7 2. + <_>2 11 2 7 2. + 0 + 0.0236142799258232 + 1 + 0.6586478948593140 + <_> + + + + <_>9 14 1 6 -1. + <_>9 17 1 3 2. + 0 + -5.6427798699587584e-004 + 0.3853296041488648 + 0.5196040272712708 + <_> + + <_> + + + + <_>9 14 4 3 -1. + <_>9 15 4 1 3. + 0 + 6.6903959959745407e-003 + 1 + 0.6004235744476318 + <_> + + + + <_>4 7 12 2 -1. + <_>8 7 4 2 3. + 0 + -4.8789530992507935e-003 + 0.3293227851390839 + 0.5245236754417419 + <_> + + <_> + + + + <_>0 8 4 3 -1. + <_>0 9 4 1 3. + 0 + -6.8537332117557526e-003 + 0.2565914094448090 + 1 + <_> + + + + <_>4 7 2 2 -1. + <_>4 7 1 1 2. + <_>5 8 1 1 2. + 0 + 9.9893810693174601e-004 + 0.4615494012832642 + 0.5942432284355164 + <_> + + <_> + + + + <_>13 7 2 1 -1. + <_>13 7 1 1 2. + 0 + -1.3354700058698654e-004 + 0.5487375855445862 + 1 + <_> + + + + <_>11 4 4 5 -1. + <_>11 4 2 5 2. + 0 + 1.0165109997615218e-003 + 0.4578359127044678 + 0.5426927804946899 + <_> + + <_> + + + + <_>4 8 3 3 -1. + <_>5 8 1 3 3. + 0 + 9.1216771397739649e-004 + 1 + 0.3939461112022400 + <_> + + + + <_>0 3 8 1 -1. + <_>4 3 4 1 2. + 0 + 1.0080259526148438e-003 + 0.4049789905548096 + 0.5520703792572022 + <_> + + <_> + + + + <_>13 7 2 1 -1. + <_>13 7 1 1 2. + 0 + -1.3102490629535168e-004 + 1 + 0.4879088997840881 + <_> + + + + <_>14 7 3 2 -1. + <_>15 7 1 2 3. + 0 + 5.5228749988600612e-004 + 0.4844943881034851 + 0.5512825846672058 + <_> + + <_> + + + + <_>5 7 2 1 -1. + <_>6 7 1 1 2. + 0 + -1.2130969844292849e-004 + 1 + 0.4367971122264862 + <_> + + + + <_>3 7 3 2 -1. + <_>4 7 1 2 3. + 0 + -1.5112989785848185e-005 + 0.6425955295562744 + 0.4881826937198639 + <_> + + <_> + + + + <_>18 5 2 2 -1. + <_>18 6 2 1 2. + 0 + -4.0125829400494695e-004 + 1 + 0.5372099280357361 + <_> + + + + <_>12 14 2 2 -1. + <_>13 14 1 1 2. + <_>12 15 1 1 2. + 0 + -6.5766851184889674e-004 + 0.5834553241729736 + 0.4869078099727631 + <_> + + <_> + + + + <_>0 5 2 2 -1. + <_>0 6 2 1 2. + 0 + 6.2220421386882663e-004 + 1 + 0.3824636936187744 + <_> + + + + <_>6 14 2 2 -1. + <_>6 14 1 1 2. + <_>7 15 1 1 2. + 0 + 1.4663359615951777e-003 + 0.4813488125801086 + 0.6966739296913147 + <_> + + <_> + + + + <_>7 12 6 5 -1. + <_>9 12 2 5 3. + 0 + -0.0495477095246315 + 0.0539276599884033 + 1 + <_> + + + + <_>12 17 5 2 -1. + <_>12 18 5 1 2. + 0 + 1.3017569435760379e-003 + 0.5337455868721008 + 0.4160748124122620 + <_> + + <_> + + + + <_>1 11 6 3 -1. + <_>4 11 3 3 2. + 0 + -4.4914530590176582e-003 + 0.5997437238693237 + 1 + <_> + + + + <_>1 9 6 3 -1. + <_>4 9 3 3 2. + 0 + 1.6592369647696614e-003 + 0.3727185130119324 + 0.5115634202957153 + <_> + + <_> + + + + <_>12 7 2 12 -1. + <_>12 13 2 6 2. + 0 + 6.4695458859205246e-003 + 0.5252035260200501 + 1 + <_> + + + + <_>8 7 5 3 -1. + <_>8 8 5 1 3. + 0 + 4.9810269847512245e-003 + 0.5256717801094055 + 0.3934406042098999 + <_> + + <_> + + + + <_>6 7 2 12 -1. + <_>6 13 2 6 2. + 0 + -0.0385369807481766 + 0.2061924934387207 + 1 + <_> + + + + <_>1 2 9 18 -1. + <_>4 2 3 18 3. + 0 + -0.2827565073966980 + 0.0618832111358643 + 0.4925057888031006 + <_> + + <_> + + + + <_>12 17 5 2 -1. + <_>12 18 5 1 2. + 0 + -9.0301828458905220e-003 + 0.3157590031623840 + 1 + <_> + + + + <_>4 7 12 2 -1. + <_>4 7 6 2 2. + 0 + -0.0438662692904472 + 0.2033682018518448 + 0.5164769887924194 + <_> + + <_> + + + + <_>6 7 6 1 -1. + <_>8 7 2 1 3. + 0 + -4.5701069757342339e-003 + 0.6611183285713196 + 1 + <_> + + + + <_>7 3 3 2 -1. + <_>8 3 1 2 3. + 0 + -2.3362410720437765e-003 + 0.2807789146900177 + 0.4962876141071320 + <_> + + <_> + + + + <_>9 4 3 1 -1. + <_>10 4 1 1 3. + 0 + 5.3960331715643406e-003 + 0.5146387815475464 + 1 + <_> + + + + <_>11 11 3 1 -1. + <_>12 11 1 1 3. + 0 + -2.6297608856111765e-003 + 0.6284487843513489 + 0.4955588877201080 + <_> + + <_> + + + + <_>8 4 3 1 -1. + <_>9 4 1 1 3. + 0 + -3.8577478844672441e-003 + 0.1486748009920120 + 1 + <_> + + + + <_>6 11 3 1 -1. + <_>7 11 1 1 3. + 0 + 1.3963800156489015e-003 + 0.4701338112354279 + 0.6320971846580505 + <_> + + <_> + + + + <_>12 13 6 6 -1. + <_>12 15 6 2 3. + 0 + -8.8699469342827797e-003 + 1 + 0.5286818146705627 + <_> + + + + <_>14 13 1 6 -1. + <_>14 15 1 2 3. + 0 + -7.0626288652420044e-004 + 0.4648370146751404 + 0.5333210229873657 + <_> + + <_> + + + + <_>2 13 6 6 -1. + <_>2 15 6 2 3. + 0 + 4.2645810171961784e-003 + 0.5084878206253052 + 1 + <_> + + + + <_>1 5 18 1 -1. + <_>7 5 6 1 3. + 0 + 0.0615721009671688 + 0.3629625141620636 + 0.8757156729698181 + <_> + + <_> + + + + <_>4 7 12 2 -1. + <_>10 7 6 1 2. + <_>4 8 6 1 2. + 0 + -4.5381980016827583e-003 + 1 + 0.4856696128845215 + <_> + + + + <_>6 1 8 10 -1. + <_>10 1 4 5 2. + <_>6 6 4 5 2. + 0 + -4.0877899155020714e-003 + 0.4584116041660309 + 0.5420240759849548 + <_> + + <_> + + + + <_>3 13 4 3 -1. + <_>3 14 4 1 3. + 0 + 6.4308601431548595e-003 + 1 + 0.2707302868366242 + <_> + + + + <_>6 13 4 3 -1. + <_>6 14 4 1 3. + 0 + 7.0455260574817657e-003 + 0.5057486891746521 + 0.7026523947715759 + <_> + + <_> + + + + <_>9 14 4 3 -1. + <_>9 15 4 1 3. + 0 + -2.3246440105140209e-003 + 1 + 0.4827278852462769 + <_> + + + + <_>12 9 2 3 -1. + <_>12 10 2 1 3. + 0 + 6.0276601288933307e-005 + 0.4247249066829681 + 0.5508763194084168 + <_> + + <_> + + + + <_>7 14 4 3 -1. + <_>7 15 4 1 3. + 0 + 0.0180845595896244 + 1 + 0.8104801177978516 + <_> + + + + <_>9 0 2 1 -1. + <_>10 0 1 1 2. + 0 + 8.4693520329892635e-004 + 0.5154619216918945 + 0.3514379858970642 + <_> + + <_> + + + + <_>5 0 10 5 -1. + <_>5 0 5 5 2. + 0 + -0.0269310399889946 + 1 + 0.4886888861656189 + <_> + + + + <_>6 6 8 7 -1. + <_>6 6 4 7 2. + 0 + -4.2346641421318054e-003 + 0.4622378051280975 + 0.5382478237152100 + <_> + + <_> + + + + <_>5 0 10 5 -1. + <_>10 0 5 5 2. + 0 + 0.0269471108913422 + 1 + 0.6366596221923828 + <_> + + + + <_>6 6 8 7 -1. + <_>10 6 4 7 2. + 0 + 4.6446882188320160e-003 + 0.5368506908416748 + 0.3765429854393005 + <_> + + <_> + + + + <_>5 9 10 8 -1. + <_>10 9 5 4 2. + <_>5 13 5 4 2. + 0 + -6.9577661342918873e-003 + 0.4234687089920044 + 1 + <_> + + + + <_>10 0 4 10 -1. + <_>12 0 2 5 2. + <_>10 5 2 5 2. + 0 + 8.7609712500125170e-004 + 0.4672406017780304 + 0.5350683927536011 + <_> + + <_> + + + + <_>1 4 8 3 -1. + <_>1 5 8 1 3. + 0 + 1.6103329835459590e-003 + 1 + 0.5732762813568115 + <_> + + + + <_>4 4 8 3 -1. + <_>4 5 8 1 3. + 0 + -1.2848590267822146e-003 + 0.5481799244880676 + 0.3784593045711517 + <_> + + <_> + + + + <_>9 7 4 3 -1. + <_>9 8 4 1 3. + 0 + 0.0102435396984220 + 0.5155907273292542 + 1 + <_> + + + + <_>12 8 3 12 -1. + <_>12 14 3 6 2. + 0 + 2.6889349101111293e-004 + 0.5353189706802368 + 0.4387153983116150 + <_> + + <_> + + + + <_>7 7 4 3 -1. + <_>7 8 4 1 3. + 0 + 3.7903659977018833e-003 + 0.5032002925872803 + 1 + <_> + + + + <_>5 8 3 12 -1. + <_>5 14 3 6 2. + 0 + -0.0293696802109480 + 0.5873538851737976 + 0.2215445041656494 + <_> + + <_> + + + + <_>10 0 7 6 -1. + <_>10 2 7 2 3. + 0 + 6.0743088833987713e-003 + 1 + 0.5417029857635498 + <_> + + + + <_>2 1 18 1 -1. + <_>8 1 6 1 3. + 0 + -0.0127107203006744 + 0.6056511998176575 + 0.4985181987285614 + <_> + + <_> + + + + <_>5 0 3 8 -1. + <_>6 0 1 8 3. + 0 + -5.9445449151098728e-003 + 0.3352069854736328 + 1 + <_> + + + + <_>4 7 4 2 -1. + <_>4 8 4 1 2. + 0 + -2.8927479870617390e-003 + 0.6929240822792053 + 0.4778220057487488 + 53.7555694580078130 + 18 + -1 + diff --git a/plugins/libzm_plugin_face_haar/data/plugins.conf b/plugins/libzm_plugin_face_haar/data/plugins.conf new file mode 100644 index 000000000..4e34f1d92 --- /dev/null +++ b/plugins/libzm_plugin_face_haar/data/plugins.conf @@ -0,0 +1,14 @@ +[libzm_plugin_face_haar] + +cascade = /usr/share/zm/haarcascades/haarcascade_frontalface_alt2.xml +scale = 1.15 +flag = 1 +min-nbrs = 5 +min-obj-width = 4.5 +min-obj-height = 5.5 +min-alarm-score = 0.4 +max-alarm-score = 99 +image-scale-factor = 0.5 +det-cause = Face Detected +log-prefix = FACEDET PLUGIN + diff --git a/plugins/libzm_plugin_face_haar/debug/face_detector_plugin.os b/plugins/libzm_plugin_face_haar/debug/face_detector_plugin.os new file mode 100644 index 0000000000000000000000000000000000000000..7eba72d0333a072978f5b455ddae70984cff97c9 GIT binary patch literal 1777048 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

4U$lGigWeQir#kF}hzbO{drE7fvz zDt9{gBSw`h>PycztLZvVy>a&#rP8|m8(`5zkL&vjGE25+TDE1A+cU{t>=9;?ucore zUMbq_26`KpPFSX;Hxe5@mh1$`MsQWO9$TOlqci7^j%Sy=&LfE?iFX?%kIDxyjMn!p zFDuBtukwK^Dg`knuE+XJn7>V*so#dg_&<~A!S1DJIr>ucs1}AoJWS z_oOnLQ?GTVc5HS^NBpeZ>|nMN3 zL<&926s_eY@(GK!vB5VRySi9xszs|#xCZsQCVWH#Gm)D*sKVmlN-NcS4dqKiyeU)y z`U(Q91k}b+`O}VR*;|N@r*?GY4+xUSdTlA^9NIx)eATbv8Y;i}!(t1q;-;pe?4R1h>W%UE=wD393E@j#Go{%aG!=m};2! zQcQiL41Or^WOHsfqgen32G70rEXPSQVrCb;Q)?V!_ifb$g7wzfGjPCiEOR0*<<1OPP8y zb|h{kzpX6zbD3II7Ic@XNBH?$GjI z1-Lx?_xyYVCCN*=1FD1fsWHLDpsz(uL%?-X^q+<{1m7F0J{6?LQqz2KEK&CT_o$!6 zf@LSE=VJ%GELZ1a)2cf!9w^TgrpJ6V+e9iWAjm zDuT`v)g2WF{^UgU+lt`+6V>t{Sb3tlB?zuRQQaRLcll)D1&}@1CIU8yehtf?78;SayPXap-|N#;dQ#gKgv0rg-q|c=hvm&@o>9 zC4S(;ehE0 z{DT_xn|B0Xu2I(x50=-cFANV}9jERce(=lV)Zc~&UE|c3_6|0TQ{Ub@ST#<)uy^p~ zajJXogO`s}-`Xd5b*%cyK0)_b_53~uJ~>t`ul!kT(^&O~D)RbU6$RhCFD1BdU&>96}y^={gqs{OV7i3J_|6Kl5Y zPi*?{{fT|A?@z4!(gY3kQzec#`_bfqUO~lIlG$!1E6FzoDAq{GmGN zJXvKA3LZIGed(Z)cb%-Z9JKe%C#%056yQ01F!|qnFva=rgM<4{QJ;HP@Rd{4%6E;t z?iBU2ckTVRlU3il0z6-P2>E~E5Q_8iA;HZP)lKgXS|_Tny?f;LQ`B?s-n;7*_4>O5 zJZBFj|1TX%asF~>@VANTmcxRVCaP~9Hu9;7>V?DherTdtiFCkuza$*?}(AFo~r(E#NOSfs_Tyo@O;~m zcL~*b<64McgK$U z?CI*p;{rV2b{zSC>o|(@i{q$$Up_AQ`RVGP{QQ;UgTB+%1IGt{I9;vh=U*KkkR%*W zo%x@~2bB3$KlebT98Lhq;r{~UiE#m)hui#gs z)iZkqPmET-=I5^t3zi?D9vK$AI$HgNpFi`CIf$7X9{k`4b=UCVjw93$`T6zX!HY+z zTlNlqe1!Vu-t_#veWoDhO_f3BNOezT@Yf^Mqx}3rCDFFDD!6Wp`chS}@<{dVs-y7y z+p6G)N2dR6pG}cK(O zzIv3pwR!{`o2rAaAEmx{Q1IAM>i&a*yN^G+EIaA^M?k{9Hp{{{UQcOc4Y9k zqtrJ?1}`0@R`YY$NFr>_7_={>aQKMBr(tkZif+keqo}MHo$N0Y}k&Oo$8!{a9g?@?1Vo$*>@ z$btP-2g3zwj>F-e6x6CSB`$cPPL$^(gYjyDJUe;BM+8SHx^$hI&+#8l=FE{WhR)Jq zXaS{;2_~xP;(m+a@ec%Z6kS&Cmdp0zNwMS4x%}k{^->InxiV$JYZYoGiNP~vpNV}w zh`nBpHd46&K92^;9Tf^LN(b_bR`<4pV*4J2$may}V{{4oXJf-Y9Htq5$h#C+d#Sp3 zB;p)Hln|{lQ-9hKf_Z5C4i5JYPFx+{1gR=Z9SQ zqrKD|h3I7~ZmmdCnOl^n-PsG%#(jiz#rUYlJS(<`@-1{6d0ksP@ zz*3JL#WWAAJ*g*#UUnh7YU=}hCn19xR;YZ8o-qpH3kyFh3-G-K7_9L5UirK6tp(V` z_`ExxJnJ~_-VnJJhK`gEIux{P%YGXRE-PnjFG&c-Wa1f-;uQe zZkeBZ2(F^f#75%6`zK@dxDNkX*!h9_BXuMyY=BJSBZD#OSczNe`Iw+yeO$*mqBeLY zhWXGRV(Q}HbYuS-3z!Py zBv3b%1?eGVw0v)fda~?P+>d=*dGNC#>igvZ?)H9^pPwi{6#joMr+mI%F%|YwMSu%} zKOY3RcK9m+J>MN9ummy`#eRqWfX*s1|2`1R<1YVc?YG|{?^WtQgOxG0WTaB7rM7#h z+;zMxW!4nyY{mTcISwr~F@+WCTZ}A{0W~3*r7k>Fw<`?~qtM-HG^Y_4W5nsP6DN$t z7To+GQ&x^?eNU|XPFUTs@*nW?`dENK=tt;uOzZP8wUv4lZYJj8gM`{EMCZ4i^7~?0 z`E9Y_@3C@pjbFyfALnNb2?*R!7Tj2-ep*H&&CC7fXZ6)!we9qC1ALt8C$Zo~C~K&I z3hE&E3=ypQn<~_ER9LP&cr;L}urLv*XUc;c1NH0j;GY#3X%YB0`tyvatHVfFek6Dm z<5{pZMk?jUG3u17V`MTgPxq!MQ?P#2CQKhTgVvD1Jr1r+2AKSOD7Y5mU~C+FMF;=k zCm^b09PE6KRqr|<>s@!pg8O4sb1nsb7((F(TAwuX5Ls<2YVQu9p?UZi4;@FJgdtrq zKDZ~Qz7Qi*_6bwz8ibv8XY8*rnu%#X6nYINr+2K01^1Py)so9z9}oT$rWLZpZ^v!# zjvYX@=_T3NgJm(ENp2|{2GtMahQfEmO2ogrRQyBlj-Byz97=X%M_jEhTUP#XTwOmT zfY#Njjl>r?0Rp}rYhSny27h40ESKxzGHdO@YzBRSJ z0#gUj6(1Fxh-m;n_d6)`H(>M=R;*Eq`bEcaZ&jYx*!8Op_Ju3#4CwV=Uhmc~Q0bL< z@t3vfQtQ|Q#wwj&hv+v;unAE5jj(O4hDce+zAEBQMch~=mql%7fjg{V<+5cECwK8X ze+6%7{WO|?eu(F9%Zd2g@;rZ`f#0WiKGpV*9nDyPH;e6pZ5yiW`xSQggxbkObe=6I z6aFp_V(03rK{_^WaL!4tYoyJeaBo1T4R;XihCm^o2C*~1-O>JOTG%|VX#u)zQ`6$+ zQ%}95Va}|E1y|3S-2hi&Zo|C!jdK#Sn-*NrxM(rrC0Z8GTX1PYBAbY6cEkMniRPw6 zK8<*4#x+3z{3|&uy69IICfP^9f_Gx_rJm3$Cyz5OLPjGn3Pj=Nn>_8>4Aa zqK*kTYH=bVWL}0UT+-OMATfJUV*|(?tIlj%Fn8XiEsGk6M~S&$bV9eq;<0M%{H9Bf zN8RVnyGo6n)7X6c?1q-bjcV+?%Ns6jJRU^PZ#*6ZHa9I&V=r&G>iCBF4T~;^f72pF zx_sV(LXW0PK7RaVjq@(OtXW4O_m%VJG+(Bj3oco-SdE=Kzu{6fma|u5g*nVb{Bbx? ztbX$rlaz3Ubmh>J3yx||%x^-wgM*1V4b2UwCe&Dy-}ISN-w?9HD9e3G%QebmYjbH4HurS#+zDOkqaNOja zv!ix%$uEKp!T}3_lfuQ z27cp@j%L!^epwtq4EMf~vfHXwCl@)u5C+Pr1g9Ktdvpx8M|sEFy!+dgX?Zr4!L9n4 znH|$Ic;^oVW$T~C_PbX+sL3wrgl`A-Z}DzSOZU`FsOw$gh;DB$SF2?=iboN>0_*R= zzrCZqM=QAAr}vxf@PdN|wJbm!wy74Yr91@pZK_R>06Z}$>Uj@a=NS&?&7(O_88P$k zEI!oQ(UVLKecqtIF*c0l)yygNOrNx-)Kl5I*}Y0oNz zj-f03_$}+17~pZLHXH`vjKaeJuB1@DSvC<+CL`V(Pk?K9Z=8TatH_B^jdW1zx$^{-emuR};XILnU;xS34dL5I?jcMwN z5^=zV4(t@^tG1>gjc5#y#{AHfKFCx=ns>RJazCLDchc8fG`*%Cew!KJXzfCO%q#R+ zo$w^f7}n;F4u%lF3?YLcN8Tf&cN-wzp)t#`Oy_lTC{&vIU|OM|hHpT7TGZ-w*y4p& zwkfi>W+j2l@L3zQ9~s|uRnkht2cM7bY|3jlmQX2YSLhl$rzkDW{xA~?79HM4e_GOu zag=2{dcklQl_iBr$m!E&1H{bDd?(d2`u#kZkhRj2wW|vLo7~BnNj1 z*R15av*jWsmz0PIZ;DII?r7(Nl6D0@&O-xtXIg%VM(KuZcV}n*GV_z(%5~M5i(W+o z$s68Q)`$iSV>n(Jo;x)!k~WXxmW8Tl>#*95$1qAI94W%RwvOS&^E)uiui9u!%CATs zte^1W1@lOSg%#>zXAmxyk1G|sg1?q?dekHR;f^F`yn$4rXJlyL!$HjYSMkj#e(25A zRrrb(+NT8?lV1CW9a>ib=*resWS%~HU1oExF2>$;EU+u9GCw)`@l01PMV{M2Q+WkB zaT1VJqO2mZM${B!W^RX>yA5$bNN;xLt6@U&OXX5==s-F{Yu~(Le;RLdi%>G**;RDU zg}j(mjL)@k8vMDII2;;}wwUzN=#f;CETP%Ns2!s{^r_)&^7YBdzE1_fd^xC%jBe5V zz_@6P+Tjr&keBewOl4d9ij16X9g%pI547GH#`9NbyrDtADyA21CK^_NsdTclCgQfN za-{Qv99Mc6-m#S9pKTpBGd<~vj(k4U7;Yi%QYQdP@`2g3)6bk$#c$yqSPQZj4sB} z*OWTl-;JHa)MC?m8V4Su#g;H7#*wxq-8)+FP7!F&)lEbp9nSJ)ehNG~(HJlXF-gii z&F}u(^kJe-ClMzx#2KDM>sY_0Km?3WC<4YO6oEBiTjP=2T9d42qdiNxdUy%K;T7gU z@)bc)spFY-1yo6<#(JVeN3p#>qK=NY^uLZO?*DIejq!kwI%=B%pEI76|oBt(c?P zlASN&;JQR`MjOQIBSF%d&F{Bu9d#xJXGb$rQ-todRi0bI^bIpQf=yuRMV;2B3O!A> zUPVdi6zp!;Dws8+>W~ExB^F*=Wp+k866Ed8o|hjiHB5zReZ1L-w#cSvFa|1jvC4@! zh(&oS-rY>m?T+?0MUjk!Vle6PmNU6b38#$?H{5?a!2dW;x}#+%-&ta2-ew!4_1r9s;el5~uzA#9_L6+&)#@D}=?Ssrq-;UI_{Q}7A zt?05Vp!)D1FR?o$W|Au(ra@-vBlK5?n#N78dYE=e(W_TM2d#9H;jQz@+Dpfsp81iR zbm}9VE<1AtBCVZ~`J*F&xGKSG=j5{AE_(rCZgiQZJUiX%93g!p1@hvS3RJv=l(Pf`+yFacaNP`DPgou#<* zpolgu8VA{7jX>5&xWl;p52W(yBT8c=ceSRSu~)BI_F>I39HT(D=uM`5TS_yIl9iyy z2pHYRrl(Sl)LOoP2&`u?XK5~m>KE!ZJ)a!xs$znNqKFd8MVAbF2Ux$R_GZcq>4vgU zHX}tae|Ew6Qdoaa5_fy~W=J1nhjgCb7U_gM?RAxVze+x^--cGkVhJkx( z^Y76%yS>K@&|^#6OoIsVbdc=~_6=XE+wSeCrD=Sd`D(`rv-Xd-m?y1o9G$b&$R2MWq>nlM;4$OBcM5_!l-kZEmxd)3((9`9%?U0kRJEJvey@2hg?eHW zGJq#G)=A%Lbt?qsEO%*ZC(VpHq7E2ig$)6#1Pa|NII_A4kY zqKn)-BYQEi0dX&2oRO`GW;Y|&J0sKMQ^9e-^aB1+CYv#^CD<08`Z2MFti4Ffsl-dj zrr#=|rIXMW3l_u*%@kvSX(8N(j1UVwpjb>Z@KoE8+ci?3=OtDYR&xO-q(v4QBP`9 zblkz3Rbg9^Jn%+}w6x8z6L z@IEa%6`Gw|AN@!`s|Z^{f?Fs%fTs4_ksFM(kCkI)mhQkP$$Ib9oY+>wSNgg+s*D1m zHVyTm7y@YOI4TK>tO#l6|FAwR+OOXXWkwPTG_GGl$#LUgs&h}Bl=9pEO|;Ws=X@o4P-cB<-9O4xYbM?Bn~C%GF+3J)iGH@HPZPhoh5Vo}I-sKR3KgQrznDU{lf@ zMM3>dnY8l__KK6|u3!O~OUT+?J-}jXa+@$u$JP^c#Ky$e%Y;&Io00jo%Op*vQ!sU3 zq?M*3!y?*RXc~!xzyhlSY2%zlG@V&~Km-VwZs=~8J-ieFO0X1h6N!(hyv4^gpPX%L z6V!%7-7TX~tjBMYp|!ktO~|h+4t-P86c7s$nCW`!qT4oH%&(V~)=rci{)75K8Olxv zl$0#-gR!xlq`fkk09$AFF?+N8ss{XR<2hC*=`pL)@#r_B*brnxrN}Hn-e3f+w$sOS zNa(30El)#1H=;}XK&VU$#YQS4!Z2P=fnig!4NcZrIft*)8NNr)Vf0yb)wZNpHOr|* z(Ol75Q(Y#aF5R{++~$U0evOp$K?K;vxL3W^8Od?|0)k3d(6tv_Juk|MpZ9_o}TZyK?KFXQ6cvyHxdbDucyY zk#B#s#}ngSMpHt=v90+di6pExs6-jm7PuNFrf#Fq51zzy9;YbG$uYR7SL5(tj_TxY{My&QNSlXatA16dhrbUUI z+$2s!d-wYHd;_=krtD4Qx>8mOQ<-&{&QvBxR|aSJTW-i)-yaM+LVw*2s`@Sn@5-JF zIVXKLx+NTHN%Jk2e9WmXGPY#8OYU@w`h3_;2-Hl+CsngWIS%d!)0>kvE2I6Y3w&w} z9i~}aaq7VZOqK~aU*i!(dt;gfGSa3zOsqN1AeoAtO z!{Z_=yLznUyo$Wfhn}gxKiG%<`+QxL|y=m}I$;88zxemSuB`Bs)g zUb}!VEeP;I1j+-}Qz#mq?WxOvJbK|Z5%)yby|K0yeKNUiW9=D&X9`YZME)rgzbC^) zLFIB?Y(C*RaQ~GCBGwY)MnYqI6xtfOk>Xw?lfbit?FsWY-6DqH=b|sbR6@PvOEI5QCS`_Xjw)vkkHWN z_;;0Fs{4TNCKW7}?H()0^hGv(TrFg6vCvA3YALJ3oOejy(w!#|U0AZb7$r(7LnA#c zg(vVCnr`roG#my;33i_`c$$T)FoHK+8`G0i#{aIOO77}WzjI!Az!f`jW+Hp*>vqf< zr0LNVB>auYKykw&OrP+qc3xTC=WOxKMAt8Q(nY3Zm#Hl+r5sI@fKEC;MJHgJNt!p?a4&8oDTI>Va$H;(c77JngS-3um}E4KZ=x0Z;J^&*>j1Usnn%X>^=cFJ1c5LaoZW zJjuzPvGBxul zEVaf@wDy|T)wR>R!L^W>P7u?P;w{_cDicX>M8eysCz1lh)XvCmEj4=%;vSU=v`^cH zT3#C|*zqd00Ru6v;@(xj-SA|}HfM9j3bm%V+mNUQ1Tl+Jtj_}5)ro}PpQ-2K_#RVW ztx6G!u<;;4)Od(T#}F3}p=Xw6XRn}C3DMTDwT4{K$0b9}WGaBI;=VWsOvcB~=+n(D zT~DKDCLBo|$>?o!3qbxf=NJJV=%Di#lH?Q0+z zp}1vccIM9m7ab|X>L)2ZXv9#B==lO^8APOAS2qC`9Z77QEbttj2mUJZqJ^toXGICo zd!5#?+{V;5d>b#M-n~^r_$~D@akAzT5Z$NhP{}puQ>&l_?!sQNezg`vtx_%LqHu(X z8kn5CtGO0Fh^2kd>tw&Bo~B`2T&ijJA-Sgi&6MTIm$BfQMPe={98mO0jx}_9O63FC z)60UgY)iKxgkqx>m;uIgO1wWtDy86sw9fo6XGOPdL!DJeG|?mzJe7HL46oL&rrY;Y z*|c^^jd@6mdUbD1ZjI%eP%>l#&BtgGKvTAJPPz0H&ey3FI3jtu`!UOtTU(cGRn0Uo zB14@Kf9B7+cxWa2Pbu57x-FMx8XT=s3Mlqtthm9C|zxpocFgs=cE-I%@xQNYfe z<^#ByZGmV_EnPFD)Mo)IY zML!dkv%$d~ugpJ7;L2Lbssa%ff zWDY3 zLi@WMj)tQ$ampp4wF=6N@XP2$VOW@-jYm{~iLl)=G{%=4g;746hTh>aJLVP1W#d|! zZBVoFTKh0`Pvnoy7w6u)ou&eGmbL|G4C%vrZV_7m^?TdP38mGFYG}V$t`)>8(mn-o zxRQQ*8cTwz?}zwp3kl-!k+Y!Yz!XgOl3Z&`2lMhjQpDkeaM*6nH+w|peRLThj6M{P zu}LSV#?Z;0BSlT$PTj`B5UD*&D5zrE!(oA((Ip2&5~4siXYbqyAQVMb1W94j_~B;U zjS;e%y?Hys4T6BW%OD)d`b-47st2(i&-0K79W)@~rJijl7ut)A&~E*%B5hODdh`_` znJ?M2RA-2_4yAQO*F&|`&&Z#S2}*+2<>Z+u%O7e?e=f|7e_cjcWNJtglF<6O3%T88 zVysOeC*7BM;dT`y34tN+ax_m0kKwb^C}~X%)molxJer_5QS;^GAxHV0m$d+# znF^$c>_(bVPz5U=fc;b7xBQH7rHX`I%Nki-!VkW$s*J=$%j^HgoC|B`cQ$HkW7i{& z?Rz_`hssmA5oruqV4gV@C0w*!T{?H6R%V+(v)t;zusup-BTM38yq(A;9CpMW!j{wN zEcsHHUV@}=1z=g8Z_$AAGM&U)R2(d~ggHAVyFYj8y&yI%zHkO>vTzj7>Ztl;MlUh5b^u>bVViJ@rg@DGYSomA7{7skWD^d#E-A@@II;gNl)6ik^Sgi(7gYEB3Ul zu9=$&t?y!FM`B*HO?Mc5TiZ< z*2f^FI?`{rpjyA62raTI&6W>@m@F2j>^j%-DY}e}_@&nF!_ii18jiG%NmS~)6e3By zi27FKgjzPUWIKJ=B>8&VlI`m1q45?eJe|{H5d2CL#Q6Bh#ykKcv^-oT%7xfrXA;+{oMQ?i+;}x&Uy= zW`)nE!P|Q|6LaZh9iR3t_oh-#qEei(V>vdcH`$Y!1zBJZALkUdE>FJLy5vRGGAp$M z?MH2ht0))45`%a!J+>w&c6oAB>yl0C(?gJQ6PB~Dfvku5q;}*M65n$5H>S)xf;ROV zGhdYO?9A;C{nwLEKAGA4+Dn#@r83eqvU zPJ^NOk!a?BRa1>uTQ=9 zypAKrRk(cKEd~r3kzIy~`k-N_aq5{5Vrmvgjz*e;hTf%DpiZ;)Rt(BKv zqtYepe4e!K^&@mmNVs9F5Miy|TCW{&2yO<{DGYZz!GwmPb&?L|EY?>(#QcJN;RWFJ zUplwQ7XxnFsE&t<#E>|%lUn8>yw;BBuHlP?tGaT8bz}6@U)X3Vn(fY(w|UUz>2GO< z#z<;Sz5WG`&9&z9qo>n9`Ro`JK|-%WI zs{BF+RyH{g64`)ZuG6pJ&O`rI1R^Uf?i5C7F(!2LPpts`NZQCKmY7*6On#1-XlMI#H{K<`1&2C)SJg;fNtT~O%4fE!Y zubDl+X+h(xd6zGoKmDBZYG#d})VOF-)1q1P7R+tJpN}`rZf;tHkXhqTxTImutcC?w z&zjw^xH(C`{t2VKBlB~g$*)`{VkW#aeS;>)WHo4XX>y+_gR;1vO=7F>y7?`a z&Rd`+8h3vwby%tPJ>i6gOBOdTYM9-OCSEkJ;gb1{i)UTluy6p?SWsZ8{Kuc{$j_`x z8WuMe&$(p!2`qWD7B^nru%H?8S5UHFze1%@B0P|D=KY%?H zS=*Zyo-?!=xl1rMx6spMUuu)Fpk^r0S$!eS=ncUdEb?|u&1~>rYr@9hwB@5mJBOHP z#Rq3>DpR-~r0tK@bVfMVDKD$#tNoY$XkS^X-?pKKH<0zA({1_Bh9wh;+oHvSDdDSA z1H3L(_?DqAr91znuoPRr6oiR)sx-6TuKGoa-G%kjtMdW%5jhuS<<>uvrWYu&ju&zk zjp>|>-<>&WDbsCTn?|S_@T*U}y69Y{cp0{4a0Z7jXOKG@oWoMsMBOW;r6`XN zx9K|^IGpxqjT0iGrB%OPFft68=!X=XrujIZrqTK2E||#YF0wcVW)IeDfumCwe4(R$ zGuhb>rW+Y^GgtVxfT!g0X1m-^Ij8~!`^=JBw@24sTQf8*CF#bhYi`c6~#7ip!*iH`Tw6=p`>lXRiBK}-Q1CarjQR8T@tD{7so?lex5LAUXs z!NNq9dfQ7s3-$*pAE-SO_de+lrZ^ibx@{wU4llWYYYGDo1Og|Qb#AgxiJZ zTsed5mx1HBvh>w5XJ+B4}Gm{XeB{GhUcLX3wh|O zfj4vroJy`Se#IMfq7+iIbG*x+jKj7>e&>TE5OU|8E?jSxx|d5j@~Cg(bL2)wP~MR0 z*)zWICBf3o9i@ZTS!o(FwP$=$#f5p#__AkwG1j=Ys(A?dUo^hxi%-q1Jz1qM@7goM z>=|KPQ+dw}My1RoNROp^W-yL1v1bOeX9iPp2BT*k^f^$z=Odgs?T(3z*!zXIjQ{VL z$rL*e8qVITVWQBCZ<{sjGxP#JoG#OC=vz30y1UD?E1!J(hFd=4>%-i( zT31*f$~A{U&#l9ojBoqCe`i|k@xHng5{n#_<_}#vkAdiR32|S53uy%T-{O=t(%bR@C;R;1uXwI zr~I&R9nh@5Id84+zIO%8p3c(k-Na!3e(OwoHSYxEstB_F?atYB0>0ksv3yZ)^uFkn ze~EJ@J%cjKwQJCKO*`T!*G`+ltn?w9S|-Mx(p|2-hUt}rEG2nKmu?{D+IK$xZ}tw_ zvs${n_wA7~yfK!JQ}bjsWYQ^a#dZzK-TjbP+M1KeYc!um5H^~r%caPThVc9)5~wiemzeRbZ2Tm{x5 zFeIC|n!}?G?#}Z72TGi%gS&s%nCPY+S(;6R-4A@`?~J==E%ey3khZfkk1l@$H-z*q zPcH+eG;w@yN6UrcGL<$va%al-;dL|EVtuD81D6>%Rz3W zhRdbLdB#FJJ9BJ86`TT)Z-E#?r+o?!UE1D>9)i#x;IKx@3eYf>H*+65l*%=g$)zd8 zI*Sl{Grev<0^_Ayjh^d~N#z5~O1(F8B@EZCHlJMmR=BZqZ|*!aM>BAVoFN|<%F(7_ zGz#talNroIv5W@*8uz434uLOa)v{pm5($$RMrlIH=2Z@uHX`*dlc!tB<&6x;Nt zk4e|+$-Y0wV)P$Ozmn@xh&M4D5cP| zy3o_KwZm*jvs;T{up<*l>dmfLu8Ho;@RJ$&cVEkZ^D9;uMg{!jsB2#v~M2|k*kTAj^C5pN!Xwz_l+sP^Q2b|3G zQm0zmfuL~o)0#HhK897cGX~0((-{W6NvKswFds!V*{C!(^(VrE8w}q@ONTI1V5S7y?iJDyl`u~&af%Q~Wqmi^kHH_l}Gn9?+KC}Z&ZNpYtx6{vT zq~I!-!fSYOW~gfC?oX}So%g3&)BDZbp9(feb?J4LqScMuI$ZT;?@z6g`%@z`lVTIq zJ!6L$68{^=4!eRtHh}4Pw200t&RQCcHeb4(&6bS*HH@Tgd3B8P)M-~_FW98 zc7Zr7rJH(<{(*BmKlk*C148i4!i~_^dnOPW9BNh2ZZzgcd@-lZpIzvrHpg)a#+dMxVZd zKFhUo-gA^QNPb)K*WJ(}q0Q*-6v+C1<+2Xa=-hOso%K4R&_ru9ZaV%L`8NM!to zDj%cEbqgfL*odAL;|~(WEFP<8sEoewGX({f#m?kgcoTEPPT8YhqytA6y5FLHL3`Jr z9U)5i_z11{;XQl?oCBM*zGWCMQuUO#` zT1&$QLNI^E+?gITRrKkaynK483e$pD{1o#3hnqs@!QXR6UU8(^?&!JY$v0Y;>`=`o z^JM+CF1)YUy5tSjT#4KGCnx)^^j`2pWOySIjc%Qps(cNn$|PTP(!5$MjY)xz4!jY) zi<)F|jOl18{(267K?myC8f++U+osw$af}{Qn`*0^=W6FU;XIGA&!STY7zEw5R}|Cd zuL@7J4UDhLz*^M}?a-J3VMJUO!5G`|j3~9$bTI?nTHa~&Op3+@dgqv0G#qi5N2s(p z^vbV)I*F20Aya$_j$JITQu;_FktqJ63_FLZ2+r+pBt&RDYW$m1(~Woe0aMHTX~o zJ*M=hPvjGs@|l#$d_TdJhaiyR;2g?n<37EQ*3q`DhExlG zS_QKMT?mFBTAtXL%ww#ewO4J9TKQo=+g<7S$u!E>i3-(#^UcYXP&7~=HY$73$8kJ` z2Q4CB!hyGU)VIW!a5nQ$`A5`*)RQI-U&E<}CQV;uluyjiqkLj!a&mif1=xXs)^J#OM_;npP$oOeGpTJ!hib0E7i9Qt_t#oFCMP$vjAD*v)*o9>X=$lDt0t{qG`w|5UN!H{ zNxUHzqrS8wamgg1TxsuG+AvzL?QhKN$l+vHU(V*5P+fcEGNw^9= z&a=|AB!8S|*(-?C^A5y})@Kbq=>8_!>3$?bJKawo9I}mAtex)Xc3LIvbpPb!8mFBo zZDBhhNwl4WdoxXZG}5a68Y$$Q(+2ps1aa;k;2iTT<@7MTtX+d))tvmX+%q1w*Scfw z(ha0z!ug#)6De4(a`Y7XRbOah^*J_H9}G}Za8Q0cq`2;cxv#^SEg@<*k|cnh5vMQ1 z=w{ovj~6QZQa05ZOAd?1MOK>sKce0wwivG-=AIC`VL0}xDk-o8ffA*3hDT65v^I}rZD=s*AN<0I8#%FO!B)X#biEf-y-_(yNJ6nxs`MxF^xvR<6DkM?O+!INO3baCD|lB z9JWvqVUlB8MoN-MbSdR5F6Bj(^eeR~No}R@(oiSi#^e_Ke@gYdfRT_sxK_FBUldFO zU97`?$vf5wPOWr`Y^+?iL66CX?qub%`+OfgmYZ-pmaoAYcgY~HSh+Z=$S|qg z5)-cUyn)5o9rX2UDvyS7!)=U)$D(a+O~sO(;7+V(6JmzJr;V$;;c;e%NpRYv${W95 zib1zx%-N#Hrt?wOt%I!FnEvZ_>!N7g5<2rz70C~!y6;GKQH|b6KGpLIX>#k5msRsgDfGsueRFE^sg?r}t2=h(J_M?TU`_0bD6t}g z>pj^34J{L`n7@b*5hZ`cjH_IBPDm_;@KKBiCl z1ht4_`?6o|K#J{hMBkL$jK)>@IS#$!K0VTLO}b`(tRpx^GrlCbMCd#gIrxFRIAFSi z)(Ie&Cq zKAyMrava6O%EQ(17mi09_2Rl0pLpR>x>~Sx$yU|8Zz`wnj+4nke#i^oqrhL?PN%{_2H*Iv)(Z~iE9|N@Cz8yY#hW-q0 zzaPcb@7f}_#MWL#Pa&@F30O6H0`6oOjb_+#eL)rSRMbu%4uI5RWK{3+7K9q5Bouh zV{sJ6`IBAbd2CAsd4df@7iN*>Q-f`NW!Ff)-{4LJb1B=hh9W%(Ee3heRuRp5SCP9d z*+rW+GHKTa#xlg8}X*)#T*&bn!0Fw-b(DDZ}t=;u)O8n@Lmo`y+!Q*Ah_V!KKN4rl@7K zz~=mR2Y*kfnYVy%=a-Lt=#P95i<3^tr5|0I-DgU%8~9t2+)@;}G`Y_de|PY=$hRZ< z<)urL`%Luh0{#^xhw>im&!x$Iru1c1elA8nqn)Beqxp#)7cFV(b5u2C!qZm?IuNWa z3Vsjb?Ygx;QY?%e`+8i;yfBB|5`BO)4C8BEwlclWJHGvWl^{~k|GN6s{?D{uq}W~9 zeud|o{L_K7fE3x3@ZN6#DODW7o_fAG@_xhr#OcNVE4A`Ygzt1q)zQ(HxBEmmI#Bd? zXlJ?7IysJMzETy@2vIjje$UTNgMWE^D20|+FjQ0o^A4iYgQ_Y2K~e9)f1PGNJ=!#vYgZg4vYKQXrYuM!4w7C8 z;8%=v(yMyhq*rTKB)YB-bew^_s z^LWPNC)mdglkDSG>MjM{G~@@1+jbqQxCeu-dy zA+2iK`z9llQ%#%61&GsAq(3G;n_nC}O|d@l_1y(rA#W8veh@bR)R-;akm{73jWKYYA4OtzeS z%PY9|mB$&lPO-afezALqjQtQ#t%&_RMm=GFa>Tk~T*Fan#Pn$@_6u=U=)mX28Q0Di z#5r6$e<{u??R+stjb1itgm!Kf=l`SZJm9RTxxasNciFv2aTKIj5CrZbD@~N%rHUXT z2m(t{iU=YI(gf*>1r@tkKoq-(`Y0+EioF3=R1gHQAT|&w3cSBllFZz>Jpbq2&u8vr za=tk^Imt|Nlg!-;a=As}6XkNNURIXN@Aa~pT>hY!HRSR~y*#b#6_*cBn4iobn4hd# zSEN6iVSL$0E_aw)siv#8lFMJrSeAB_%blvKn_T{GZfCf+T>hcbfpYn$nZ#)a%jGV; z94D8%Ic-kWxkmh2*8IbUmA#mZJgBPF&4=_-9eY?W)v<}BRDwFz=w*P`Of^+JwJax* z;D2yqil;6^3_lmHLxAtV9Jx2lUPD}QeFEKxFjsgDbA9qA+>GT?=Jw=oNK}6GxGNIo z4vs88Hev2e-VSkjSbbOW4w4TYnJ{-J@1@}2ixTFZ$xaBNlD`GRxP?3s~tXjDu znUt(r4FzAo#izTscUD86W!Lk{9{x5{zl zZkW4(%Q&o}!z8YdC+sS z+eOoq&!wh`+9xY2=!H#ld~S7Mn$LvXIk*rnO|m)3<>ZXKrsQ7e)6LC&&855E<|gTG z$jEPA?tGtadF~#U?&WBH_R`w9BKJL;uCn`+NUmPe9W@eM@zg|oO8$ApD9rg+Hsy<*ca*ihB8Q#z$LpoG zrV~`9=6{l2YFAOISTE>76GvA2IKw6G=B-?eVmQNrrb)3*C2WSxREK)cUg|TX8I$gw zvX`2_z0~sCOD(@uRYTliFHf_VVr<>A{1k1bwrlTW;Z_zt7X~M*cC?p0`LbK|vNy^- z93Cj1+R3FaLRj40qL{?@MKbn5D|2DqZs&u(d1vEUM0e8IA!8DzZ{9FguTJlqC%FY; zY2Q5cvSe;Awb1rb3vD&mjlzx8uA;olkdxTBKCeVc+dHw1f!UJR98r>VD~Daf*p_z| zM5q{)wjw{MkHNKQ+MY*Y)p1<@3|y2QIb>AAl+U;2WS>{amtH%i>5k9u>2##???G7l zO4d}_oSJ_khNa~KQz!p7$jT2*n7a9NZ_<;!9;+^o|2~^Ar*oF&*_ZY6$(QBvPiPb7 z3|5dRJ8sahgekPPNbyd~e;dkOLpwA7DP)nXN?rFngxG|Rrae=VqGMD+C%x2$dv^XE zaE8;@SueHWo|8{L!<{0ky5w)*%(V`?=I`fAt;2Kk%dsl0!*2N<`BGczdHLh`vK1^n z1<7!M;b6o3g|J$}&GNrTeDTx{eDYA6wDV9~f#&(eKo(Dxz~_mSS8xxW_bP0We+mn0 z;PYtejhYd_A8imqvcqt2@zjSd@0R&JI7J_Po=CXeyXY+ zN2C@SoJJP#>9Q7l8r73emyhJrn7jEj?gc)L|A-aR|em>27gHN-z@M*SrkkVaKkx$pQ=hM1B*rZSU!BJH^eldYhUtY|zucq_q>#z9q z&0T!j_!6Hs?ZHVro70ZJcyxN&eNXAMbSbn}!;vu6FMJ;pwpEruG5Lhi>ixn#Rq3Xnn<0B2u(TKJb{blj!4sE z#7O;)4NfAUVMq*csB^ zjtCoA2Q|e8Qb5~Uy-}}&Eg*{%^{${#a~~pVP^cAlng#A7acUT1VDvpE5x5VuzO&mL zd>B=I_Phu9baQG6UENZdPxD*w>DGaKx@{_-ZePHsJC^h5&d>RD*KR)DUE&c+eosX{ zEojZBdoSVBeK+vw{^$7gz*;^n`jJnIk9w5SJye5F54YpfBbV{%@tgVd)Qfytx`9v2 z_VDSsV;`e*&!54k|8(Qi3nTgT;#@v0f0$1%t>n|ocRx-EURlPc73=x*>MlOLR^|zk zz21sXZ}j8Ss%d;$b044He4S5kZQ;|~$tNknJ5~AgZc{$JSH!3Hr}6272l@2j8a{or zkxw7*;nUjVo}%RI8t`fT1$_Es0!}s0KFZwB=Mv@>K9@8bah69=v0u8OZ{ypg*ss)b zCHNaP>;kUwVt-L%Fi)U|2o51#koz>^QxkDrXfR4BwvXhOQ#<{b7!nIpXhvcN?q4VV zH7Y($)Z_laAKyr2$|C(yl%7B6MouV|%M`_!I+n7s6w4@y>1kyFp<;$=D9Kbn)Kx@L zD4tK?sRxft(Yzc~kgj(e#W|8&tX&nDq8PJ{sB+*Fsad#IlPWPl5hfS45Ha@@ma$u_ zlZ+CJhFWIG(@m4|+R+s|!_e)IUIYowG<2iZk*B?D~Ha)L-MP+hKQ+RdpA;mfF8i`#(#uIYmW)F1`?5w7XZ zOmR(DET@!p*tsmDB&Ma6Nlmk{n$P)6)h22PQ51^j)5}vg9GU9tsb?L|Aa#8vk2kLXG$ut_&)}#^rZ2)!p2N?Qf-5;M7ESC#*>Z4F z4;P$r=Wy+&3$FeNg%x1hOjs?!>2nc0laf^^n4i-FQ$#dnk|?;1GDSvmb-P@p8n(pqL2AHv_av~B_xf_sz=4XiUa?$u?l+dW8ZLMcebkk7$@f^{OD5jA_yh;&V zWh_e8-L3~pu z3#i;S<8KI{3Nt+b^mUMxZ+7x=kj-&&u3xESX|m0$vhUflCxLM;^1)3(jom@|%t`vy| zw|k;FiwdM^<(PjV$vMFqVr^)_5S1^-RD!e)5nLFlgNh_qP3@V@G3~+h%iu^uz_9wD zYe?|~z;m-Cutr?KEH(2S^ANaaJj*J@$O3u#<(N+(mWKsNrCBO+iJG|Q$OtVhQE4lj zXtl8IG$u)?mf4ClbqG~KKpz&Ft4M!`{6h$RSmZ`UW;le}jI;pF=oUpDb_kb<3oYGX z0i}^)OOAP)Ft(OHv|5^fp-MJEx*LbKG{=d9qz;?EtME}LVX+B^z=>8IU4Zc^{*L1o z*;=BW!;=bJbI-P6LG$O0ITw+Aoj~qtY5UEeG$SFH=!GXhX(Dwl>{jAsa}%TwM~P7B z6kB6n0J82#SR~W6<~wkEJ?q*>1j8~CzV%hap{`<#pEjE5CQ}pAR-SN8L=>rS$|p^C zFasQ?UxQ?XQgAXqP^zHdW)hG&4hz^BN)>o&A&4hE#mzve(>?VTi1nW0hO1N`rl_5o zUqI|~R6>Cv3{WdIB{7#!28TYn+L|Gw1}6$=-7=A24YeRVg8+VVB@~$GHFSlrr`Moa z%wXUcbT{U52*-O33S7@X9s##NcvnmVEsCOb67Vd9FU2(6=QVr+;a4#Y?=nD@W_Ck( zAO?KwfwGmcDuP4(phkY`fiod&<^k<*q?o2V1Q(M~9`CN5Xtz}G8|yKXfXsoNOkQS%vu)((R70`fIR|#}J1h%&X$`Yf&3A zu$>I34B=@GkOzlS9hv%?sP-Vb6BV+gtr;{fQBdSnjQ}tqLzO_Iy{20L+?SzA^Lvmf zzIk2*vD#DNo978nZ3OX?r@}YS^PWncg03Hj+8(-jnoIXqK(}iR5NCKQlwd~Nk<;i-+QzzumM@nxF7Is1Ap99 zCLzJi8Hr-fD1|v+e087(_&C^Cvhda;)jawcupJp_tf&o`=f`?(b@cE!w5aTw&}~p~ zu2)?LSSydRR{F433}BSC_5n83qZDTwtPGWynhs)ql#)@E*2t~JoClr+w#uU}??|;g z=J{{H{&OTgUN;MU-5i(3%ma>a-E(%a3i{k76I@jlTuBsi2Uk@KD{({!Jx0_K_P zP4oMcnvE0-v!(Ktq(lFA*g*NB`8HBWE2g$0qtJHT zhMO-Si-g*lh0=cLGd6)NGkK?CoeGD3&*Lg^#@p}HDdx@T;93wXeLX##tpAGTQ^sVq z=?!9l(`bRCJunHv=`o-j18d2q1rR=%2{hm8ja~uadI#`V&DdRCP@ffYA%6k;ujlEG zVcr_o#-rtGqDFD3KYTr?>-KvqS_A9uQLYQh&T1X#wT=Wf)uWjPG%t}u?qgf;0`{~= zodFSpulB0n0lOg!uU0gd@gS?-1uUn~l`UrQ{a))yz-oImW^g@ka7SSMJ(}I%6<+m3 zu-9ebt=m5K=tIE%_k4u+1Kg8QjVnydT)nr#UxdH~1f~`c$w@vhdd6(kWMY zJ%A1IXw2XfJvt58Egp>-+|wKU1hADJ&2Dg0ulj4SzhvQUlNjVx7psL$1vs?1#|-Z4 zwbljJ+M_XpM|!P&fsOHKc7rE-)i;2>FAHxCp5ax$2<#n?#tgofwbImr`3~4FkJ2p= zxrvrCdNwN0l&p2?j_R4gpv+OHveN(F3-3N!)9g0rbEbxwc$W~8=j2!{Y-4S}@UHH3u-Lz!Je;JnC` zf{8oa!oj3HE;yyhD7$cQbt@N~b}OvrUZP<7-3YohguCmyH3Z5O8F8OpaJyU`aSdVe z=_vO=B&Krf8iE+FYY43$L}`z_hA^3&5nDqzOx9q5COw_RcB+0Q6_@7+P9~X`HzqG8 z3f`no(-iS-NY;v8bTV<(=&+h8UmZ#89;XjB_eAG z3|!)bVlS86&Uja0*Akaw?f`fn!QI%iku?M%mP5LRhzp3|Hf|Nk8UmF($9xN9drVOs z&gu+QeU70UAsBtTV!i_f?y3{GPoI@^=k;X zA#$M;$nB`J@K2g$5WMPzmq2MEbsL(A5-*!iApI#ygi5E_8nYirSv)$mT%^cjkxbW` z>foAs*0qla_JuhINKppHPaDm2lNkl+Y)`l*B8t>ESVOoI%tMaLwuUeY_L|p#yyvih zouS>ftRXP94aD!B;%1Z?6t(9rO+&74S_1nG=#8443ISh26{s{AO^@90t1sEobG|>8p53r zJW4`&yt{T{r}uRY;WZ%dMKN0?vWCDpZ3D4`D5;X@8bYEm-n7FJ%E@LT-x77t z*AQ6KX8^WjXwv*-4S^f{0T6jjTz=u3N7fLSstn>ZPlazDSwmo|J&5j}3f(-qhA@t9 z*O4G5dMcEot|2gWD~QLUlz%X(`*jV0`PE=Q^}KsH*_x6y1UBBCwfYY43M0boyfl;UiIm7x+-Z-V$dO3A27 zYed!%IPc$q6>E{DSmA1sH3a5Q2HWyTe7tUC4T0WSwrAN1xU~) zTO#K@n@H9WI8i?&n2;@zAJj+I5UAbcm|KzJX`jm79@5(Qo{Fp?NUC>{Vq3OUzLFwq z2=X=ZsMdDqPkLn(+K!*IvW6g3-7J*&wYjVzkd5YSPy=zuFhIUZIpZ_d5XOU>Nv!ns z7$9p1WoS(CEri=M0bN62qYp!PTpOE3;GD(I zwkF9M0`qmiw(>mPF%eYO5E$(PY=lRhYSr3Y)({w-1ME(Za$S(X8X#*3j4lJV%A=VE z=o$i}-vIm5qt1Yc!Lo+He2KHL2!ul`(DBw_84ohr09Xf)#tfD<1V#q|yTYR}gJlhY z(Hns+_NX%;Vz8_sF#jspkFxOAZL)^I=#Rkmc{FCQtRXOZY+JlffI-jAm=CQXGyr?vk$5pB zMHAgT=}(^J0KM02mF|%O}t9RHKMgUaQ?*bY?xT9WBVf41AFr{4UPM zBvQ}dEKx%w%E;AFxk}2_FuBT=t4ri6C0E1cDv+y7<*IVWK_f>d@XIvw%LIIKPISb&!Sy4r&@3oM{AWx&jb z{C>~y`#CB;4&r4Hz2?L^Gp6$LkgtPmqm#2OwjjqRrI@=RKAeHbh$`{E$2KP#ctEb#DFsnRANbojs z=ZKpdEBBdaNGxvFmU_IQ3Z^A4Kxnxq@wIDdm7|wwb0cUcJ=1)L*IRHYcV?I2gK)d&$?4Rq$MMT+}z^>_wy zE=xZ*<`oE5IiW7M{0`TbBqRqRN@ig5CYV1Ext9d@u|VUeo76d&4#pwz!D6=N zAylZ$OXuBSOd-S#J;G}kn*JWs5rY0+NaWtEuS3$h%D6v_guL+_DrTGrPPXs;21y=d@B@Zkw=vL>Yy}$(=#Ah zXv>q=7RghlD+p20jcXyV9G}?M^CYG*YSoMbH=VR`9R$=E6Wv8F_hF9FOZm!@W8|DC zbwRGmF)Jvu@EzBVHQ-$k2!8U~*}LAw+`>|)qXo$7>^ZGzmq3c_Kc9+gF728~^x#mJ z^89l>i7qE6>B$bu`F812ImwR8F|9erE+-^SdnD?DBYlXSEbGu+PE4AbHok*M0W z$I;91qFmRWxqP~SUs>+jzdBzHYt5%ii}*BR98O}_OVGr9W@HUL(UVNg&F{S);tMD& zpZbz*<@`SPoQpf0;`0ZP3f%Slgvjsr5mbv{;4dtYrRV%Xaz#HyghUs~RRu{@^eGah zC@~J6ZrSNPLpmUcyyYL*-3HJ5Dk=_i<1Ox}f=%c6bTr&dFD;%Lq+J%J3op=Lew~~B2 zX|Qsx;9n@_NywJF^Z_+O3k@J846OsO(L;YCVIoDolN-PAVwc?kMCKuP$u3}0p z8336WhA!lqDjY$OX+}aWvffaIZ85pu+%4z**ruRTI^R7*-8H-3+LYxaBzqwaWm+bZ!Dc z;cKU&8CT(UfC}NZQ1}M5N(ru{1|-2%y`V>Lsx{^TTr45Q$B|2H{9EQl#J%I<G{qJkW2iMt_}Eamj46P_ zCBCew4ZYHT7M3&S8eGkzoN95MsGx!|3lX`@2|^XE$O*=*hWKNT)Q5(ImiA;WM>hz~ zPx$zqsK%Uw0#zAkNm0eodj>ev1O?=W4K5)KH6d)^0I5W!q`zl1-9Yqmlr=;iBCKW% zgi{?5Q6ptyHFtq{$W!4e?C5QN4a9rdsdJg)9Jhh^ohUAPq&dhI8K#P(CXd4rrnET} zc{dhj5Q!93q(0~$o(icv=pQ4CCHVLRG#Cj!K~0Ju?bL`|z^0$@J<@aRe|g~3qkL8E0`@i6L3jkflsWDt#w*wEUS^Ce40cd~`5J*I~XUNHbcc}&%w zY})n4{f{HvjvJQ@Q)^E*ravMtb%G#;piMQ$T!pJ^y|6Pi+!VP$o-eg;r~E02S%QzJ zh&+$=t9&uZPbK+V`1mj;=LdKtl5fYy&X{~TrSC-=i(QCK065fs)xU=1WDkDr2w(l3 zJpBBsz0N5)8^C!EvW4J>BrCZTvhhwHQS!6P>1F`;62v79%D`x=X}8PiKLA#GO=0M; z)ASX9?HQWncCB5U+cTH^Fo+Up4pMT-PpRXWV*geLQIDvQRj&2AfK;Bn7p?;@tv-A& z^uyhv_d;6)IW65mF5vEkKaied|I58V4^(E{AnJdG-M!EagXt=4tG^e>pwPX*m*m&l zqkGyy)gCj@1+N%^pt~2&!wuCNN4kjHs=pU5MdWxV2+AU8Q_V5g;_5apyclT{DRM#h zUZ5oAS$w=iz8B6U`Feb8h{^e0s7dla@v$!^=X>FD(s)ciYy!uj_J{8Uvd7ee zthtj%nlaxCtmFa!MGmrs*ho%fCF3ER>Esb5d@nF`FMvl0;*tg@!)U9C?*-0jC4djT zrZB|!0&Ch1;Li+Ak$Ztvl|WM{k3&i>`9 z?Ttnwla_*?Lc0pFGf7kMs~_A|ztr4@xP>l0CmuDL^Jrv z1rjNm0bwI5q}TmA7)I2(G1Rov8|k}0-;U``KaqqgDE;jf6Ld71-aOR>x6F0H@7{62 zZ6CSd_aEJ4HEjRX1%Kd4U)K9m#T#rH(tn#t{V@rGBYiriUyV*Pr4Jc%D766t09lnvlM7q8)+aUej!);mN*B-gmm^^%eEQ3Rg ziOe_EdXS92h^pu`5RDuaoK1>kPf+?(w#{^fbbu$ET{;d*=ZS}5jF|*%x^TY0QM)Lk+Qtc0Du21F$e>D916&owN@J_OPB)0*C(0J z$7UgW5d$hq7Z4X_rw(#HClECj#5AJV5Vl!o!_zrAlpFTHLcBNw;cb5Da!hb;D*(Jh zP{<~MWOE{Cwgte>3{6^%^}VXRi!g}AA*yW2nliv@3LvaaK*V`xc?}&QJU6DHv)3>j z!qG7eeHb`^8Z*~JI6tO={_QWeERo-ygz!19K^wvt2F$wDX6 zv?r;>vvhnr9d$8&^#X^wlj0(3WFMia2c$y==I?XqE^A#&Mzhv|Ku1P#oAqrDngig@ zC=^g?TY`qUgqo*-yyUS9LeHO$LVOJA=Z>(g>RuKm%}z)TI;q?&^wdnq7o1ufD3_!u zGZ>u)4s`@Qz{L@=fKh8XQV`b^%z2(;hj~vZEEC#Ea|ysn8Spsj*#tvq|$Rn0LKSYDLodQMbljG4(jy9Y$hwj9F(~T}7nUki1GRr8o6HSrPJUkd>V2mpN2lo zr(tjL>5@%+8vYlbE-kr_5{#(Br;+FJY4j*Qjk$wQW0&)3+*f?M((I=M6Dsm)Vm&@h zYRRX`z4$b31fQnQL9h2~vT;=?T&tk4dB|BWX3V7$eNym!KKmFgjy| zxe3Jgl);Qp#u#DlL7YJfi4U%YG?7}4NH@YP4{0?==zvJR+EpLY4gxeA;6o|j8Wh}s zfV65di(54XoPi{-((;N71FuHx931K8Q3LNp++r6Wyv7DnUe3UmaPgKS!b4!niSws` z)LWzcnWcv#e_FVq`;@CJe-0Ul{RTCFB`E9yi4>*nMDca=&oO1j{ zlcq8hoxj}By^CwPe91^g^5gCKcqIo(l2vQSkTidVG2;<26-Rmvms``lW;FX-b$q}wGn;ITG%MUerBEv7n$2!c%Y#M zCQO4Qxm3aplW$M3;l|0elWe$2@^ge`sFHs%7yEN4GtVN|mvE%Np(_gvV}LwmK7sHn z0=^3aBN*t5c(WTH2RtAhP(JP*{GEmPq&aQ`wgchNJkQ_Xswz!+EDI&$i6o>tvBGkply_vNl#M%*^0~~El{lqX zyEapJ3Jb;BoteTk3(3T!DLyL0TKSeJ%_dF4u(h&jM^c`Zneud2D=7!Ml-iQsSm z{o_zW$kB3F>y3W~vpME8FpWGHzFpffBIPSW}nKQQ#r3 z;VcNx_8Qd4Cm5JUSqz47gx8?JQU-1yU=D;g#xy+VH9P|0(=iP%dJXSD_;F0bD-7^A zk)I&^JqEna01Zz}@hi~kaYQ}2+5VPKofabuI6@ZIzVtf3E4>j)u8qDJ|?!H zGdGuknB*zGAJrQt6{ANxSJ`bK7G|f;^wi5B-uD#Mr91~z;S`U44{T31RPXOk8O8q3 zv6%YCp@krow#WWXkvb5!iXs7X>W8or;t5aj^FVW|DtcBzy519%QxMLsK(HTy?DH6VD{S`x&eN10mq?t9Lp?x0x*5=i zHNLiJI}=DVhuMlQ#=~l^!V4h0$N}=;)6&U{Rg|}x0%9&v^4#OnDOHJeu@4r5Sel(` z!{%^~?}GS@C~1Jj=xbE!c;uoA+cV19?gn<)D`Zruv%SKKSK`|Sj<7KQP3eE#&})ffR!i#akOK=f=$(7&| z8s$syQTkFKU*7T`H&-Hl3XXK{7W#%QYh?LP8*>vP7dSz1A%Z$vmj5he)Cdvgd3?M= z&{3SakvxcAAo*D&{}dlz$KByD5&Q%NcSb%1#FdV zqpwlo_}^(SVHwhsU)OvB4X)09pvSL3KNh**&%Vxn^A-OGeUH=X+hxv}h@XSNk#3E< z%vImt#&kjCg-#GuK+vYzZ!X2vcrWb0cW4q3TG)eRBwd@^@o_JaU0A=~bxE%0ohX8N z0m4^fKpq2o3HSoSO);PZ1Lu>{y$~KEK#HJQ9Lqo{#G4B6U^N^9Nc|~wyjRl#L_0^> zXH6BaW&ngE91u|>zf;4tI|sykqPW1ph3pzKLvyUf3K?An?9~j^)xQfwUml_HS1Iyt zP^$MZJZbn2E>*-et@}Ak^(XCaKPM)wDgvyGBYo_5bdO5qW74V~;@Y_QpaP`9b^pRZ zWL_^pIuSUXTWvf>|C`%!WQ?gspLI+2nK2zNPExq!46-zb)_D^pXHP>WXsq)3Mad$1 zY;kKXDN}6>4d5vp4i2OzodARAS=XLojYQ0&E<%DgQ5PV=n|WG>6VIn{n#A5pBeFr5 zVjZ0*xxk!!6+A#k32urPN&G{`G(u!2Cy)X0FSJ!eix`7z;vbwxl%b zlSujX!0yaIm8#42Pm0Yl5X*_G$_6RWgn=&!SP$U_r^eqE)HM117@gk96-~qB1c$T!;VJ?mt#Bi! zUQfU`5N?eDI~gF8%)bz(rnxe6Y1G&MFvYF?6cDwE3RR0z`8*J0&vXRQBReHaww&WA z5R-`twHVb^opo`Jw}V)eT~{5ZSl25c-p;P8vDdW)#Ln!x&S8o=1d}%%OW!!M*foHu z%ZNG+L?fa?o^V4-?t5sdf@87|JO2xlNYPUFeUp@^y5nWH!ZiAZh>7pW>xLd)J$cP!3r{6u6dbQA|n?GRxUMjQxQ++7y)L|bq10gFB^g!aWQ$QB$ zY7|a3H_mbw(@e>kFqhJjxjbMioN07drd-a_OZf+)g|m(9=&vkOD}~n>^AW80j7)r* z3#WqXjrjqQyPP0+o=SHy4iv#0a`9TGMCusWQktZNQ_WcrpTXf*%|wK0{3x=!4EaZz zZ{Y&g_A=#rK2rC=k$!`%P~ZUuC}%Sc!m9{)D-4ipu-u7wa|b@|^MICPi7`tN`2q<< zwF(|H<{dIA_DP@G7SE=684W(ThJIz-Fbj595KgHP;Fb1Z755)R2jUL2H(g2FY7 zCC!--H*<*2;TC?tQr_=mE`(H))-3$RP_}d?wREPmbS5uxQz1vXKq5s=w-b4z2B5Mx zpkYvq_xv7S)R9`)YiJ{|g!hHEoBzYDMdJVE?dB3bXlP5Egbx|onJVGK;o6jO(?2lN zRGAGkaHQ9BWvM?)Bux`UwkE-sEa=CjFFZPFOb^5kbdq2bF}YK`YWYY1Tlz&LLW{+UjJh($7d`b^!U?VF7EBPO0#sBstrZ zoP%FI!yzRKoK3ckk7Miu@=8NsEgWiri41&6KyL^K5Fl=oK~&)suVE5|)4c`-rh5$w zAbikk&;re7;CISm1%#`;1_kCau#JF?5N?ZUxY27k2x0Cuw!pR&w|EVeAgoS+ltQz3 zgaLAoX$fKb7$9?>3=D*DSPXc zP%CBpV=6&VorH3atMCw~HccVu;Dqu%o)R)JGDVOM_XORB`adrVWl&_Ufi$3^@`o*8 zr5y4A-)M^fJnL0ZoP6EXoMaQ5c?Za*49wrZ$~I%QW;eJ4j5AL$VGm>Beb33bf_S5oK# zqPar4)4Mm>jZx`tw12z`8IZIaY|`iRo^qXGO81Z}dCNN8Q?3HBA>GSdhxE7LNT&{a z@1*;h2NCzQiw{aes_&hqhjP`dhVWw#lqKL|Y6ckFe(mDbY2vAL*I^Uz9``;-*>mZ0 z7UDXO(xjI(rdXZWPG3$Xk_pN*R*>K(vhK`z82{l&S7uvPj;SvUrYNQ-Wc^5<4$JZV z2LHni(dJ5gO!0E{!BjI3ako>v=+*e?W(ne+b@9Pz(27AiB9xeA-oeGEo}io23a>Ta zL$D_*6djs;k;y|vmcbzztFN?JkCE9_Tjn$njT|Mz+s5qa^iu?xE)e$j03{NtNT~l1 zm1D*MneH(*wrYAE8GsYzfKv_(#);gF6M56MKW?T}G4U7-`jKgSwnjcvw9}t!`MkmO z-f=0CVIuTDH@k_@=te%CXw1HmuNKmrfg|0I>s8!`Inj2AyTHZEMm}D?8LaJaD1>7j zp#HVOSrFXpguy7PU6d@e15oe2jF?2~XSm8fpQhh}`>)|-c|M6{c*kTj^!`A)uL)U< zue*B@mxB}%AKb_->SaV~%F(7GNga{#%;^AuK65Bvu8_ohI98L7GJ_C(Sy-ewts8D1 zDP%lXAO&18NK2JpuF5FJBhd6Tj`XY1V!V#H_g#Fjnu|dexngX=#jlRgVsN&UlM6_* zsGC2t0p*{uPmm0>`vfV>#bv8gq@)wIDB363`+@L2!Sc646WKx!L|K9PzxD}IlE^;6 z2cUilj`X`+Zu!oWztWiHh+LE-9%UeDF%=Xn+Q)w!Q3Xoj!;LBOcDOCn+VB+sS(gwnsxRypP>K}?q_aw z;UaUl3lB8ZMulmRB!5e|VY0*`8*ZE|yV!=CB#%c}#?`us@M|bDe zCO4Y$w_y?hNBV~_Ae#smA)#pmVM`Cl@I*He&IOP(eIOk~gyf+WV>b~_gk-jp29(5Z zd6HRfQL+%olO7`v*($c12v1@Ed+g?S$?m{v9)3g2SO! zYq>Tv(Vfe6I;4$>5Z5TNEu^Cdqm;J2TXVHxbs$6v`$-GBIhok}zy-O;#&aJ|Z(^Z5B$(xtS?t6QQJB z;!>*jWfS33$TP>RgzyU-Qa|ht`QUC;6UZh)N$@A&{JUHN%AakPepeI7CPGPY3gFs4 zL0GSBA|!|Bm`*_Yc#Iq^ceUR5b`#+kFjGB8iS3Oqn+PS>yMZi?VyrI9Cc>9E|MviI zrUZOja&wap9*AhUWD}v}Z~$;{w{rv;63;<45lRk)fLl|7tU0unc8^Vj=Y#3v6zfD? zJ~k1KMC4Q_kWOpYVWdmZBUKe(6XES(7I|(TBTdoAD1uFd%OQT#A=-iIbN(5OFtECh zROVYCI~<1ULYq@6w23hH9=rsPBl@tP&+U_ZWvWAX8Uc~+LN*bSZ%lg#yLb&UnWviw zS;H_0M|lkj$RCeq%dEFOn&nb)AeQZ{lO0q;Y&KBhr75weC~Alwzx zAe#tTL&*jB7Jwt_htO19EeOwu0rEwk#xABSggs+`Y$9afatOzJK;}U5bra!@5Zp~d zc5^^AXlqM05msM}Je~vbx~KSlRBy;8LU#BD5Z`B~WD_A%hd>;Cugj5YLY@PvP&N@V zdMdCc*-*W|KP^VBF2|e)rYOqU9@}mr90&27C=yWCc9)%QBD@#KqaGtGETNkSUxV~L zPp}TPTs9H1&$og2-BbKLP{&v0Tg4Q+54-+xsN*T8Ae^0UB0LR9bC0pN!glK>!t;R) z_Slg&5l#j&!(q0fWfLKL{9XtjbwHL)gp{{g1>z&3{+s4Dk982d>kg|6i%&s&|V<$QrrMDY+lA$DKT)WCKC; z9nGu;@G(JLlAt!M!+(T=4QkUyNA3i*FN1X7z+J#r**5wbC6145A}qfsRA)cX<5!>` zFLJ@3eVzU0EB+7q9;el}%S?ir={VARriZEzn+R`3q@f7H;SPxG{yW|z@W*OqfwHWBUtW)??LSN|>$okpYamz_JK=Mm4AmMY?!KH?_A{s4ziMm4{qN|4IO zgxPq+UF+h5x{!u85t2?=5!yr;iOIT&aNA>U6Cqh@Hxa&xOz?oovWbwV`KS&`4xndP zl7rz*g!HVFDMXRYqbIrqZ=%Px1aGG9MS}BblqJDiX*}gN5e|L`n*ed71Bgw+Zz7zE z$eWx%2E^q^MXCg1-6q0^ak0!}Co=KUVq3GiiSQIsz82Uw8K~5M$-0J$NQ%uKeEdsP z4K_#t855jHK)Hvp5{^SHRzOY#1T=)O1p%T##=kQJcI!1HyR(aN`Kh;L6>M$_;NKWb#Q+%QMLE zCc-A9ZXJM)1aZZvx*fi)$kao1M3{eota@bm(cA&)Bc9;w=)-OiT*a1|SAo3iF}eXPp_>T5 zg><_ktSz#MFhTWq7{a_qt-CBBn+VGhP#MC47$BPn*)^>p>_R}O{piI4}VV?a#J&}FBk=OKQ9(-5AP))kP^2{-U`I}9UZ zQtrI6Gl>*EGPw)G?>IdFxa-2A%RgIJ;~}1X`R6pGsgEPwp6)c?o3%w;PZuxCKMf2T zqb=7E2(NH}mdgrfLU5B42EC~jqZpyZ9x^E&lSuspS5>2`#PamCC$QSEa4H64;oXkk zLhp9cJvwADmVf?6ToNfHJ{V7Vrd~p%TQ{iyX>~`a$?QBVIk$%ZDL@RRd}~nfFakFD zC^HaOBf}!i>G%<7Ra{AAybHKukd`XvPs=FA62v}*1CJr^cogF`#J%U@gQvI{WRWYz zW?bxagcgIdrJP(qngxC);>;(Jf5!3;S!$PmD9pvBKq5s-I#KCq`KQ-Q;pLxlSQ4#5 zworwXA?E-5nFvY}S^l{n);x?O{T!FOHTN3%EAjhhh`;m0l+!?9W7e3ue3H zTzlMus3bBIz2W=pzb*e1AjJSK$hoE-3g(u7I*_{m@8uuzVCqunEX_Lmn%7YP3HLKo zT)4>0bm4)9+NdxMlH_j*H%uOdZ)Os1oGkOI4L3@2X1PejQBK%VdzdB|3=UH(}G@kbsBYm((3(ex9LzdUwZC_`EP`2xC==IEuE3BsXP zYq>Ua!#j`5RS(ieM2KsY*v5qDI3LnJF&#gKbX*DPl$Z`#{t+E_LHa;Uhb;ey9WO(= zGNwb8f27FYK)N-iLzaK2{7G{V(%fe<%OcA^qT^(e(jm2|rA_j~Pjs|~w4>M2Qtr__ zCa&UKhCmvy!&N9_Fq)c4nwgnGS^kmS7m~0oRh6cc{6=tW%=hxx?P z%O?oymE|9Dc#i1^mO) z2FpJq5IMyOq|@3+PqY+0QdI$#e{KV_&~sZEX@WjR5iI|_2=N++Xa}axd0GDX38~B` zAU``S_>D9v6=C*Sxdls5Uz`9kmVoNumi$BV;W@nhc%S= z4_-&X5%oi8`R6nU>&F0D{-Lpp=>lPo7_gd4!N4d8uk?U?>$A&0H$ZR~3E9m7)u62{ zS^lYp&fGi;;x$k4{ixoMR&W6oD|q?(ZDfGU*bA4Y2cYn%<$ z``a%6bOX~b%Gn;$cy<&CC~Ld8Q<@)FW&w~#JVsVnLYIGDh4fudunx6cmVemi zTS5HhDSjTPrBffs@(=sq2N1imQ*B)5U`j5>{(l_mhrjs2 z(;vC0LRtRdY#RbQi%`jyQKe-0hl@}IVt9r^rMhyqtZNpCo3rbZ<)0_1-9HZE1+Oby zP+9(YmZ-HLzVW)kRA~8U4~Tyqm9e7ZzT&KpE&tHyo4@_IZ`l6_Y}XR*qwzUE1|rKp z7h?oZUmVb~@f#A|5s=^_`hqRNB{a&H;G^`VK-Ui*H!mZ8C64qNTWAd5M#f$E4T(<> z`K=QK_akUm2hioA3qpk1i;qJDHR05{dVsqG^U@?Q|1$P};fTt4`KJ}7Xb4#gl1uKI zeify^mD2Zu>|!U6tlYdu5G$DiV3vcdk?Wk2`yhMF$s02Sn6_mVe#@@i|dk;9xbohSIBDq2-^yfF)47Vbs;X z3q+THX#7=*ni957)AJ~g!ljD1rjNM%Qv`4@Wz+@>JfR7*D-m~%iw`K8>;@cq@&k-15)GuVE7aj`RVD!^=NY5IN5YWI)W>rH(?ZTmE?n z7teSsj|@sJN6DmSb@`_xqRq#^zRp0ElI0&#Z2rQ>KSUi%X{;I<6P!T6aj#?EABS43 z8swBFpaF!<2@nmD=I-f*SREJDjaCqY;(2FUVHJ+h$%gzaL0EdMYt0K%a$ zK$d?hkoTuUcq0MaID$%Cx!VXH+ z2Y}_RbUD}Lod5EuEdOwARtMI=qZAh~FKxyy|C|G)cNDXYOTKQgORfNMwWqkmsz;Z9 zZijS6vP!yjZ}+Lvi!rIxe>(O*(q86;T)d>@j6lQ z9A){3bKC&p`|P@8`G<8K0&&#pth!|Rhjmp0QJ1Jtqf+Z-`G*InXM?yPyDnM&;Q{Js z5K}UA*_DtR5r2=<5T2HH%Rltk<`Jk{{)vo9x%0}-xZZ2=8rOS~T67Q6m-Uw`{g0OT z1*8)Io`NG?m+mYbgkbYReZ;kO@v_{*18rN59uN+4fR@7w$3QUE2?Jgyg4y+WWsAE# zEo?@NJn~aixKxQn_@LLOs&;R&z|g7X59 zfVVfVdDkw7rn^1zHVVcr@o#TZoV`2JJ><&1y(w4z?adBgyW&Xi4HXM-Zw^4*2p1n5 zq+&IuR+7-SH>X2*qX%-X2XHY1#@y}VwX{;ibk`4O;_b~BA>|^c&&i$T-rn3xj?k|s z>C34^^3_1z-YgFFW;YTZAk|0Hm6eYtqsTr}<{iA|i6ebnSU#ELYmv;@$STzFh533$ni#ACSRG(7Q8>uBra1%E{Let-ViS{6|o42~)mS0`) zyVKA>1lV@E3w}=-NbL59T`>F)tH?_A^53Q=zPQ)Jk*>ncqK&j-{KKlV5P7Z>1O;5b zr4i9j5c-Ez!*Ds(GdTzbwE!x;2>z7WZTg2*w?n$f!}VF=4IaTitXdB7n+}Ood94S@ zDUHdYrO2JhQK1Y;i;cjAzb4Dd9La|tlEJ1?@8wKv041a8dj0J4uLr8 z!>rUnramO98i=|?amBLDI;ZXaVO0l+&(A>k%ZdKOD$Z>rfQbZ!Y!awO4z*d%Y(9Yd zGc?(HW{OoU2l2X7WlPr7tJwhIW~asiXL$|#AxwN^jj=#yuiIJFS51 zLnjX?E~4faQL`1uz6{LY=h98cKdfS{$9#;f4>+`vD9&bmo6EWZfDTcJ^S33?e^^xn zWVpvVhn_$B538m@dW|D&tFr&F>V8O;I%(+XRK!mP`wy$$1oFAZs7De<$l8qihgCbl zB=MjR6)mJwVOc6onu-8xX23L()74u2hgIarq-h840%H9QlJy@}T?S^7*Ga7?OD~wE zUu;jFH}aXHo`CyEZ2OwB4vnOiscf34?nGxR{%pF{irti~;Gs*%**^AoJL^bL!4<1Jb$3j0P|)xSUE99*{01 z>t-Y24WxPr+p2ONkdl4oVaT2&`IBKe4@d_h+PsO654>DQEK|)!#BHN^(W~*(&0mO1 zd}8B+XQ4HbB27xnGUXsW#S_s1X?+OVMunn7lP@woA-%{Ek(aembnVVwT{X% zAiWR5r#(Q4vJFVr09orXJ0K+kF!rPzaO#f4IFXxiB5%6($8D1;CLWVW(G6w?q;j z*7NXttnfsSU_jat;+_tPRJjaD*OHN=KumU2@Hr`p4oGi-^g&NJyKD!Y$Nsqld7Bl$ zRy))JG9VpGz(xqS5%3M=9UYLehJz61er}y$fhwE@Yp4Wabpk|#jsa>ia2;jQ62kUg zg90)jy_$f55DtrJkO3)cm;vG3mImXor^=R02BfTJIE15}8Vj7|HCzwj{FnwAkg|p+A$%^TK?bDF$Sog2 z_-Rao3`jc=@GFFWc@5D4=}{Z7^%I9y5Iqd+y{QAz(;%(y2s}Joa6vj5;6< zzQXUH;LwMvwkkUytqn;_C-qOwjQ^n86Ub1H@qm>5nK2-p3g$M?vBSJ4G6tki09=s) z(?~8lAf@C<^98sciS=zZ>wxqSn4{3sXq{6l%F+vF=@%mdQtAo#A#ncn_jdK&W&iKc zT^4SQbeE}o*IoWV5~{%Tw{@;{-DMLO+|tekznkrX+pc%P??3q7YS_Ns1;gDXS>U?M z9Vq9YRMs&!P;cP7%bahp6B36Af(Z~OQXhj1b(aN@H}}jMNQ0>Wl^%#|-(B_qIMBnh zSYc<6pu3y^@oa}==`OD$Bku?CxTAubNl~=Bd;`*To^W>A=ZkcgcOh@H1K6JqwSaV& ziwP*P5j_Ep^c|G9?F}n%9kGVfAgoV-crY@5!y39k*u!gxbeAtt7Na1%(rd7fQO@FN z0&a%z&X@-2E?L7e2$#n+NO#E^)s;r;uQs4TC8ct1NO z-Q|r$eGlRfqPSw&X8TP$hx?zT$^RBV{edHlgu6@5?KA+52nyL0?k+jA^8gfOXtMRp znX#$~Ag*?*Y{{g%WHom~xX`JwfOMCv;bjO{#xzKG$r`?f@Vl4>=`Kf*TmFGCx!D%S zW+C0>cmhs@uqpv^LqxmF#t^h~srg}G?@jG4`$Bq=BW$0=-6h{nS3!28lLr(RQKQ}E zVjwSNVBGBJ`D3+SOAk`kx*q7JC~hI{E*bh8K>ik6bjg|owglQ;o&@AnkKG%3{%CjE z64LgLu&v5=mqn0_a#Fcj*yh#!c5yZ&+n8 zec{8b20!(x_b&mXBskz07aUmL1qYGU(u-lbW*IVAP9~g**wA#%yNLVD#Rp9xO{9GP zhaZvM0qI^xXqQt8CBW;0Ln^>9F=8ks;<8W?d|_Ov+;q*`=yN%Jg>*OS%&SmJDws^r zoX;J+o34>7J6$7Je!Avbq`wJAxez+3C4?S=`0T(l1 z%mx>)rPc99*J>C;r2d8!Ff^Uh57%P!l7i}h{xdCyvQoQKZ`03^$#69EUgAvf0NRcKbW|_Be zvECEW>6)z&?2ZaWhbCWSa#4}T;E;?XgAtjoq1rMvK{Rkwmg$<#5ccx`CCWBka|MvA zJ!YqC$NpCS87K0lYk&XkK1UVw|2k=B3={L9r#ZlP#Q44V`T)gc3cx^kX!*1^A3SnOds3&20=w)8YD;|?bZA8JV zQ5(Um?m0i;Zn}jAy11Jpcij3~ciL ztzQP2p$Nc-Qoiio4-v4*N10lEeUxkS0=Okt@bixOmwS-n*j{loRJq0jckf`7@J0BL9q+dC5TgGB1U> zxNLQb(sn{}ewnx0U*VT|w~?lEAg2l`L(KpAGA|{Gyv%zkBF5lI7jn7f>jJ&ZI}4Gw zJArHitw*Jo9?kuh>yu!fbDV2)s}Z%$-50 zWCMg{D5)>=HYZQ6My~JSNT0=iRbUwR0pv!r4Zz%R?IlgBWc<~(#=T&N@CyXo5YAH83AO1$H+sritWq1H$l9>BVkSQ zGOuWQ0mv$k4Gd){FY}%Y-AS_%$To*rljLRIN?fi(kQUpKS@LacwCJb|X#o*Za`nxR zOo)y)kamjcke7Ky$6!cD#B|8ZyrSb8Naw|L$jiJ^YiqJl zs;eOh!`9XgrRs6#xCY~2&=?^)tm(bO(AUK z0hu1j*WYsO4Z&a%$}L1SXnid&^R`B3ZmtG#y{GtoR7>P#UUvAyAeLpPG|6IiL#VWnM=20L%N+8Rt>GzwOJsCxJON%Gn;BnhC0}3W9R_5q z$H)px=*zsJLQ@rh59bc87b7noHTRlNJ1>x-UW!`;2itmcL zAZ)k3%zHABx*j{y%e?J@ba9xiXnC2JJw6P=u?~>un3hidAw1=6=7G3}D0%LM-(Ibh z2ahG#2hW3eBRkc`J?qU^Ahr`F4e&C4@Dw5!%~oFK;d6}1Wbpz2ayDoW|w*$5N@gQb;UEzYt%e-BPx(~!-URRh3z0A8B#CwjCFEsQD zK@D=4`-+o4B=fgiY4pv^{|ZN5ylYR|?T#dRo*%~%;m>Lmga7Y*^#S*89)b4Vya6a8 zzG!55H;=!LQ{s{X$bNp}MBdFK)5QRh&7%sE;7wEu61LsNpc(gW7Ln|ByS z_cAPQbGezU0){e1uy~z$XxXIxAH~~l0hW)-a#EegGV5`tK-ipxiIs32d>~_YmiNi$~?% zJg&`Ez&`OP#Rbeuo3Zca{RHH%C}#7O(G$C*^gb+o;Ru&l^*qbgnYxg+_5^1~AKIIh zTqRg9AQyX#ZU9SsAjBj{r#r&hBJbwi3x#F@gbxxBxfA5wyk`km0paQxu#?rZYc@jo z69J+6Q(w!wdEDBQ`!Vx?BU~*?$-8;%nHnI@$WF<-d7NWc5PgV>=P2*yagO6aOwX=M z-pylO3qU-QU6;I@$GTR6_%ORJc{h*yn;$^z%C1Y^&FexAEr|zp1sq{d*qO~5h(D8L zT(a;i6LlXv_ePKH8uZw9@8(6inE%2gQuN5={sOa~^bhE&?7Kc=+VF8?zKjg`lRmP@U$W2#AZ=Ir-}1tHm3YDrVXi(cG{4_Tuurk zQk1q67aP9;*f(Vo_2l9OlRW-kXd+ww_h~~)5}7u95b7Vpk>1SZ)~`(~jd=x;A2@;Z zP}`~W8PkSa!TjtvH*L5dQF+Kr^oA?+zfBt!B88nc+7vy4U>ahxN&lr3pYt#hOpewI&JtTl$rg= zHE|H--%D2(kUosuXpV=l3IPYhfJ_@cgv6#Pgl#+!nKrxuK++UJI+zH_BV*d|DoCz% z(twiK*#qeaMag0yOFc#&vQ<2nJC~$+3*z-232TyRL(#Mo$UcwV70OVi4Rg>HBu$w^ z=mc=6)mko@HtfmeIup`nM2KsY*v8g~j$V-VkLi$UL(wq_(&;fBGHob2?uB%5OovPx zijLPHeKV#*rVXXYn<4!nrbDI;sr*S}4xxp(G|pu>qyalT%e3J&nL?R1l-wU8VMnT}$h4tkypn|E3oDdqLrJ+QGo?%$O3DM7 zDP`JFtSyflBBC}tZFokeP^JyZ#H2ZogkfuC+EA)%RAx$y9V&nF1$m1#qA zc#b&-NRh|L(Q;R3OdE~^Gu?BP*xvXuZ78|k3*^}-#_A$w_RK}%#0t*;L%>@p0pFI~ z+~gx{uuL0D4hI3_pRrrdks-!_;*u0yL?kFV$?TGYghdbmMNmWq6i`7_Frb(PF%Se%Pzf4UPF0;#U0q#MJ!=)4wLUBxLgr1e0=a2r z(*)F~Ayq5Dvf+F%4>_(ZBh7J-(Fm3eS3|tXBI%Y5Pev~FIglSL7Mwe5PI2gJ*1l*!8)|xW!aEz{tbv<9K{CHhS$r6 zK7RSCA`Wc^Dk%sTrM$1^PF0uGDP(jBUhjfaX$X|m8>q`9 zRPlhZUj9r~HCuVLaKx*jJJ2d2r{Aemb0l`K0=b>l<}R}v)ztZ4RRe&Gc36ETZUG^C z%kuG^G4x^G(R5o(J&~Q7yPW8aR`IZ3KJ(;qDaRYzC-i>M(?V zrvNn>_?CbQrIdFT4qb%Yt@6)xKw}77IzZP!M#8^ILr(}3DZoXnfq{t-PE7$uGr&uH z_d@tk3NVg=Y*b#Yg>YjEFwp^@Lin`=rQC5x#Zrj};9(L3vT<&tP zT3KUJwjRh?HEOK2V0(f5XfadVWv)2CwDQW~5Pt_;oNi%%rnrT5Kr|tWFN6q% z_aN~{ZC0H@^h>X6g41;ki0SEdO?JBO2k~TjUGy?G7Wk;d*FkJcuZ!%a>-9Z|-_z@Q zkSQKMPlVUc#F3_rk2tCkh}J~$B`B8YFa1h&MtZ_(2rsSJq0%mqr4FYNk>}GeA;Tla zG(3p59(KI)22wD{ZC{d;IyS$L_Akm7*4$1K^Q&=fayt{EenfSG*1-6rx6tNxV_60i zmctQm3%Lp?JD&{Ii>VqQ@+@U!eOY!P(mPq1WbPrwCm1NSLPVuCKDEOv`IRrLyvk3` zOj`207sNx9^Qz4>>{exs*zouq($?GbU?QZRKMo0+7^OZyqjVD26?mYWs3zKZty`eVReLGHkRlK%;Iw!06Xk%s)s z-G}5V|9R*%%ZM9LN3)E0y$$zKH`#DMMIFX0Ba%tYGUB5)+&K2M4L6BBhp>!@dKvLe zC{ry@z$6ey{5^^pU=Z7dETs|<4kqCJFffdP{iw2<3gOKT$Y+V(eYg!kOf7-*2_mEn zZF{r(@Ks3OwbFpHnAHSXMieFcfE;odS;%;C1{WDqrSaRf6>vy75lxRVBAV(0Y2mO> zLj}q*;>XY(Q$2wsEM}@C%ZT@KyCy+8jR-M~Zuys7l;~Il>BA{H_A((l)B6J1G=WNj7aT|sWy;yAR^KhSw<8cLm?fV zqC=JuMaN7?=Q$mbWyIIHlx2_xZ16P8i0>o|Wf@UQ-%rBZ$W@VLL@79{9E4;~Ba~%C z$ytSj;heIJC^=gt=agkcscqk6VR#vFVzN+{5vibTGSW5*?qVM%qGWCW>ZaBMwC*&0P=ejV|8hk5n~u1 zGSo?@D6a+%>B`*Q;tNRJWCe0x`kdV4(~znaU>WgKF#8?1myri?kI@L05mk8%{WzrZ>6Q_H zKrU4s$hj5^4w5E)H;@@7P1{s^5M79h4EC~&NVZZVAslDb7!9(FNVZY8Lpa}Qh%6(r zhUE~hbQ&Vdh^%27ggc!ET}fF+Jf4a;2;mW@K?Aakcq#$qDk$$X9MM+DG9qg@55jx` zA~!u*Mq~|LA?%Z)A+(G*9>Qx=09i()>4{nZ;o=lPmJu0P1>t%J$m5RLefR+cUyx9G zBze%-T9y%CJ{@KJ3Bs>vDZU=HHDno)4SqI=I_W7{Mr5iDh#rn2Psli+70NOqqs72( zNQdg{dwU6*8D*$@z$}e&=8kQa5!XTdUK9zaXtPMDml3}P^0ULJ7KYHvh*_uNn*bcz zV5~#eT$T~p=CwgIb`*~XO`r?&IK7P60n&bsppt@cae5hX9FUtF#?}hgTQ4Kt2jppo z9cvkJBapW(W*jZch-~q%A^h0_X_gVGY<1je$}5jUk9*;DGg(Gt8=M28S$ayA5xK-} zAc}~R4)_NTJdeQ|+NiRO$i+?tHrpv=R8z8y$O<0?@m!KZP02DM>v|W&uJpQO8Syph z_rHSh5YUwiH&m7p-zMr*BIw|;EMm0KGGa>*1(r%$8KikRKVF@bvW!Tx@8~k(e}N+_ zg^^`M8qdQEh!U1%#L_+YVAZQ1bP`9v&caboK0Sk;BC}fBshl#O$pAW;nD6soO}jG0vz#w=oS;&eRvlVms)|` z-%7j#6@C?@+TDk15qZ;L$1$-LEt8(1cORaBWc4kuUz1Qx(kTr~k@M@<)16{ZX)-V^syPXDIL|+EF zQV}a4Tunfv4)VyAAYccC9}^I1#VDuY5QKlGXqdnNYdGaB<(+{es$nSuyfoPm!saQ! zlMGx!b?6S^6)C`S2TXu)N(%5Q180!+7ee?50o=?Whn@R7oEzSK$mB*)Taw7|?!y|S zZXbX{1hG-Hx(rlR8@LpAP`)pgtAv>_4qb9xF8O$eHfNN**#cNchf-R=y!08f`*0wT zF;UEvJByXE&1QmF;3#gf)}wbHJ`L&1j^N_xr0-^C_u>0MK6e;h0EW=J4-Z57wI)lwLw#$* zZ}MW7=y{t9c6A8T~b3-scAzGq}EucN3T#C@T6zuRQ4<^TP6Y;)vEkF2?hzi24vV zA%LA^>Jad&Ck+Vb3}LSn4HX$+4Oc-pDMiECPQzUg-j|}G69atzc@e^ODL_{S$iV6& z2=}A_y&UidgkIb>v$6Q~G4iWAnbPTyZpa>^UTE4nlhu@@a#{i_u&4pe;_!n znr$gxa60?nLR5ydx+P5iFXH}B?P~?uWmXP4crjZXy*Ida#QEyxZ|ofAbrmgx_O;3 z-=XYZL-4Z|2I0!jkqTwiz+jFeVt~$tlD!H9HJz{-r{=EboH2DiB$r!h;GEirxz6uV z6=G@#kZaOmTHOy?-5fAW9moC2p7is7?m-Q&1NdGN%*N45Gx-a`nED3HFHz2@l6^EW zm5tln$vE^i&o<&aD%}_Pu1j~#)D-&_StH!jDwn&RZ>oxi)2jWZeuTRkwZCd&27)x? zAUs%&gR03?*!@VgUyBV@vyryYrU#Ee>iJZz&N)ggLu9QblD^sd6ap!3Ak~IzO}ARv z+K-<(`o{sJl>us>(SN0?2)t@IuT(L(pc{q*+j<+Yt*2rtzcEKzZ`;`ysRMAtKZv$- z9MY!R^xzY2CsopZL)daH|erX}dZKz^BYe7>Z$Vt;l=dAg)$NbOnqlh77Z z%aG?qD&j{jSNHSFn24!&A=zc60cA16W)DVwrCh&)IBF>a$mL3PRwviSCNLcFBV5P@ z(zpbFOhQK00K#S|zyJnrCZHRHeI20fhF@DBg~ahBkos%EaHVcW;+<9?w$svUlv)bO zb5^RmgB~K!Cv&PdA>CpLGrnKXRZ`zT@PiZPVh%hU)uc}{CVk$iKdIdmCj;3I^PjGN zpC;1$-MXK9ElrB0_pPVh1T?>9XHTJ-vjnI2rEbZoH_`YYT|W0_bt{m$IN~Eeqe0<( zvHC2fmLPGN6$GSM--mPOlAe)}sW)-jLeN#5Tkfd2cagk5$@k%OAVt2Arp$;r#k35y=2L?px#U(t8Z$^YC8!YqCL}>x!{h1} z2f9|8px3 zV2tuOq>*}?OAY*904}jwNN;3iVgR{BYh)_b7Lu+`x(-1-wAApqE3*kkA$d}I3g6J; zkMgO-I6Z=cuRHRBt`7T@;x^#<2hjoK@~e@Tjd7SSzZ&(lE4BO1Q))l-{e~m{&u-W$ z;M<QG)00sGuIe;zZ9n$0zN|}ML3!bSCC0@c2e}R-)=i%WvhvtNO>h-wUSUxp%>wg6swCsTuRg?u8;;$W&DjGU=V~? zS~aE|;jSiN286dc4Uu(I*6UpCO8f4A?%W(VJQPVwvB{vTng|c1JkGuw?jBT1z7HY zfFe zmvz%&7oqO$fOU8J_HfA;IaJn7*_-2m&2T8C1Ou4dd$~M~wVvD1= z#afSEH~j|E!;awM=%l9!X5F+*11x>u(59mczz}-fv@WC#EMe**>!zKcP<4c`8v&6k zLDo$N5ilCUt5X13!C}+Pg>Vr8A^&Mx%epD|_LU$uS~cPpP03OXTjo;``_oghZptNQ zHiY$Yq$yF>O}RwOjlBj$g*t*RQPxdaS4R-N)9aFTQ`R*O#MJbQxZ$Ch6kgoW9fI`vi^5oMP8aX(;|*7_TdUH_JR_c;EV8o{iR6qnV*18e$c}! z-^Hk-gnO%VY`BkVXv6&!br@k9#K@!)ZW!xq!;ND-ZMaFSAHs5N>b;s1piF&_QV-&Y zUq>+m$PJJzrOGtLPG}tQ8^gdbzPH?kjH(WV=Q%*0PxW5SYXQVmM@YL7A!TUWk7X4x zbtNR%SZP36%$BVQjEIsufjrAu02e&;dWI=T3sT-sSI5zI)m)hlni?T|K&1J`CR89oI&<# zN`?wBeH9$KgfJ$1HOb%^ss)ga4kH)IRSjEHrOjT=L12mkjB3MHVO9a_CqIOu#06(+kK$x2XtYd(tC#p4sm!tr)SCfGO z5Ds?$^3b)RU-_O2!E6$;nFI2m@s{k>c(o?cmlc`@p zlt5-(BKcCr0j*H>YBG8jlJe4_`ug6^U&Lgn0x*|HIdjK0do_nbJTZy{RJ4A=GQSi# z2grR6qgoh3@6}uZ>C28_9f*=iWv?dNd?%8=b`*~X+VDB@&E`=^OSiUWppt@caeA-j z*+A+$jI9-}x8AFHF_4}PJJw#!Q9#C9%s5*1YO=-WKzN@8BHIq-t12p6y$E6hQ8Frp zw=l|HO}4>q5c|?ovR9K!%(zf_WpU{4@E8v~T~LZPs_fO|V(S2FLZ}qWsHSAECM)a= zqF<6iP03zO)^!bt>FIUJUQK=mydT7qPFJ|0vR9Lz0bd8P&FKnLp}m^lgE(j@_W;OG zRWvW>K*a$%kp5}$e}N<0F(d2FG@hsK)%0oYOT7n|MAkBUV7v4vTEO!d-O7C)hjNt!G4`=FwqUcs@#5jQMwp~ zKSC84iB$VcI#j)gv<)^rxC&Cwr<&`Wqts4BzOh8oV|5nlDD@dgnb?wxvtUzxnx&8p zh+1||h4{s*+iFMQf4=OZhEjHFD6cxlFQ+s_CDvJD=6}9O%>B=oiD0MVh~E@y8~*3Z zJftnQ>A@^&8@dht;sfcdo`Z0`1LhG>qBYp%yrfBaU`eusRGE_llyS2`(nYUMpQ7d??ID{UJOQovr8y*MVwzfo$ZL*>{?C^WAlMrfiVmIq ze)T(~CE!dcSldcB>rtvUc}txMBG*!B{^v^z2s=7}GNt>UF9U&$ahUm^FH`~idlxDJ zABT_`A7o~HkTq>5TVUQn zW&e%;|A)kBRuH_%{yiTFy#=YFl)4Ae<&J5HV6YaTrgy+TnFKF0^X;xu|z-M%Kl!w0$Z3h+z;VWr$Gai8DI^sK=_8!Aotn0 zJcHJvBEEodpVOcL`4_#F3COq_G*FgjFKL=Su6$on*AYRmf{Lewwa3O^4QZ$U_ zN|JfhKnO>q0OK5R6NIxJpbh>c18NBb&y$eL57^-3ePhp8oSyf9ec<%ys=mblPv#Fm zc-R3luGT)E+^dkk z1L`RVR@vM<7?^8Q|IfkqApO7+`aV{BIJuWEr=KA6I+_*)lonB=|L5Q-Kx!pn?mCy- zMD3fb)(e4lisGi|c@`Q9U}6;F@=Xi${~VkH1s=uUUd)eLX4@c zkbGgKav~ZXwoPAZh>S-~(WuayqFO;Xf@wg%ldUjN47g__x2{zQ@70OS)-= zu9|@2d`fc@O>hHufcO?nrUr==k2t%!3&+xVy*$D*?{Mtgz1vs zeGyLGu-QecTeIA%d)cX5Pmhm0m^65WX85dy(rm!^OZc7EO974ib-r8FDx z{8FoJO}2Hu+?2V4Y}Ji>K!f+G17|^`YU3mZWCg^y?@ZDpnc8i8$|)w3gcbKA#nVYK zNu*{JN>Ut6(u&V1Y};9R)wr7H$jtatXyTe=!&ZSkMWGDjVrUJ1K_{@MC{*1*oo)eS zPhO31ajb>@e`R1##+-ErO*9%R4blyxf4aw6A}QX9WMNhJdvyRgDpQ*t}DcaIO0{fs)PSYt}0WLK+JH|l|*q>ZJ`wKe5#(Q>Q;oA`S#J| zszy>=RWIs_s@{)mDOGJil~WLx!4c2rs$NEyUBs$PRRdAqQQe7(R)b2%Yc?q7as==_ zKWHYZm{twPW>QY6fnmd39BYRTaIrzi#ULSA}P9{a|fy$krAUb{>~lBA2g0hiS$qw z&|oYl9{o(l8nJaQV{LZsf5~V}^S7??&ZHW@YD}|=1E_H%MR(c8JsIqT(%OY}5X?%4>XUb&u66|KcutF6u^r`Eg%$~%Q=UapljTe&Y)UrL}F z2Z(#j*y-?i!3i01GU}SJI@+(Io(-$xT11A8PyxCspL1S*w)yej=Dos|o7*d0qqzb! zTuHeVsrCAXyMPEw_+b;qJUaj0W{cmfKAhy7O|Djssy7dmj#drXRM8WZ7V{ z(0!P*jKk0Exw~?36VjtueluC<&dgcp-#NScbkGXv(JVEv_P`CMi;c7JMM^QAodgpR z(k`nXpG9}Xoqh=JM4|sL{Y4-ZiVY{ z6pBLC3}k11+}om1I|JF-ANQ{)G}=H>>uB?yI{+nn9?8^WVbYpcx}ME!+)~cW{F6$FI;ot zxxxS5%f(;Mni5>Urcksl{2cM2A(O48>%vy9*e|6nlzz<1AjMK0p}=~_29m6-yXCpt z$iTmU4;xHCHojD7(i2b;pCbLY_dfvdGayZV1D-ld9i)$6gd3K6#V|DM40z7!(<@8b z^le?I@)P0a+UnXsa=o>Nvg|ybK-Pu^#_c#}iV=t>gO?e|I>|s+u_iYC9g({5U`I0` zXZoc1P^2#G;Z>%X6c2}rIhtC`|KMS@`(B^W-A;6DjmRlWq#iUrsY8b0 z8)5m-?N4-^j7b=GPG`x4 zB9p&Ik%9Xk-7id)sB}GS?vGR{dJ9dbTB?*;z)Onl7Qx?T@pUV=d>+yQI_Y9EdpPLa zV?xax)ZbSI>oDqw#gha+z(zRAFeX`>Hh)-Z<7!CU&Q1lgjW0G?B%xiiF>?Xl{GNA;Uoq(<) z!RGWNEniLLU8w#*LEb<-OPqmJn_i$!K-w8LJ;WYX| zZ-Ut6D5?Xarche+@hGo42O2swqLf@fRY3BU zL;*3I@tHrw_#y1G8uy#j{HEwB+GkBsqV`!U1glCrFH}#V%;%`w0Stwo`i%`PC9>d^QR~Rc0{W|G*Kyob(6Nk!H-tKAT8TJpj!eG$#bH&sbA8 z0D}qQng#;^rSaKh5VIXcITKBIt`O_me7G`t8tYd{|F(qsTxL`kHnM0n_W8d4kZa@rob?@9W~JVUMK&rJ0R zK8?P+oIaYrT742>HEoSP3dnl|ex282-wwk!Pn1&U%@|+j_<9>l8HjI8Q@=CC zYMuqL%2KAL|2Q?3nuh?-2kRdIX%08s)~mG%Vr)M|ePs-a8t8RZhI0LvqkD=w&} zN;Ac^ZwsPpl0r@C--aP0i~=z!y{>Xj*IghUOs}f~Q{*J|5{M0!l5R+ygF6!4YB>-| zaXqTZm99te?IP5pCS%Q1de^qtJR9B~n}M+FQB8;AC2bt>{4bJvR2QTstRy%ea${EM zQ71sCCgL=es5YEm+v;0(mP-h^mnu#cHZTc#Z`kYNSVTdoBUdjVNwU(3x88mq6*dUecqu#Bso;I)#jC zN_rF*doPGblN4%7dKBw=6~w#gbxDt6UEhNEHN7tBQRF0bJUYe6IJ8T+|4`?M_NYjT zex+BwE;Iw(80e6(vSny&qbEPsL;*V}F0yRXvrv?hwR5_GGRt>TqxVD0Ho0{f{A&he zi7-!-0voV1rs<>19W{LS{pNdez5CW2sl0kP;(sI6rWdFSkk-Mb z2bn*h20qo)-hBr^I>r)d?!G^QR=0wfPgE&rP(dbw=0?bO-#-XihSZlFR5k?h-Iq1J zkJN7n;+h6uB4e7n?@@vLr2JHbcqX zcMyo;C?z*t>I!`K$5#5^BXF6 zBvNg9fjW$|jL{}NxC&CwzZHqrXBA0mi8MZY5VUFm;u4}JlKx;N(v11oXHOB-AHXOF zZ3sc^GuCu7fQ1BcO@sM>()jEd5bGU9ITati1 ze^E*o4<_j1v(rFSi&Ek$`T~`GCf}rz*^JMAEH-`!`)n4BBi_lMXM@e|w!!9$5wt#= zhcXvZxep`NrWdFukoKZY51xP&y8w`2efAC_yDX8$XI&vw2XXp`sO6+T7>=MZANwpp zPz5xk3Jwj84?*lR*3=9@dxE&8!6ksw_^b%TSVvJ#MoppYGs>%Gfx3f8u36M)k0E_^ zk`^+Xp~PqJf%rH|iK{*utbIlSF`Mz(gIGHf?}UAJc$rDfueRI-oBd@|o8SDWwfu#u zU@R2aa)uUpV1lpI@JB~(e&WyZ##=3o7dc9`@6brRCfvgyHoNIickVC%EMfoDI|TV2QeC%SrT8r$I7 z);74V1A;o=C(qe@yVoJvY3FH<{RdJM(37!?5%TD<@vLjyB%gakc#?lvXp(QknB*hu zCi#`F#!Uc6yxnI>ll&$~y~s*}%OE#1U76(nhI*@hAO;cDhx6;{t4#7^NLSb6G$RF& zNq!OKc@VT{%+6(!&uaF8IAAGLQ<>zmno<*#cM1+EC!$6s z`P`m75cx!Ldx9aFM=T|iWxKa-S06onj-=?m*tKp$bSUn_UGsQQGUL%V6U`VC z9*^kz9H#T~3vI9&eWfF*&1uV%9gl8>?zuSPW07jp3)DkMd&Z^**FcILkVvrO(QAlo zvqYNls6B-0JDd&^HHGvC{Sh=n1CK{N2nx`U({X5MWC-H%h&7!D;39&!rojb((u_yF zKn!;jXR)(OBIBjuIP6%S3v8H`UJwg!IG&qd9 zr14o<*rXB;O;JupO`+^F%BvcKYDpy5Eb6l^NFSJ_h0JCsxra;yaZ{8MS9x=^&nO^f zGd^p7o$*fCXY`$@_E|d{Y(`&;>g$a5>sg;2M43mZ+`dS)9w|`AU5lSS!y)NGf6DAH z255a&8`370NaM2?K^TtU=O(jRO_nlT^y>=lBp25^IeJ`6$ZGuCt;fTs!Kng&k* zO5?K)Aa*#4ax!WPWuH-A^#iD1iR79YZ^(6)4a=U2Lzl%`c$;J7I;#t!X_OM5(HGHt zoyk5(GMn*P?D}**n*`%%pG~#FW;1NC`D_HO&z7Rhr>WdKkZL_rpk7AW+crH|2&v~^ zjs)wo&k_025@~!k6hf6X1+PBfh~H28gDFTe=3}2-MNlmOjU04q2x6bHrcM9~3F4Xt zR{%=mv+*EiIEr#IY6@kaQC{@`s7Hz9nniuK7U}OMX(6*2O0KgnLHrb@#8v-1?zw=N z&8MYYad5q1KLj#Ri+v_u7)${2c_XkBCK&aN^w3(skbYB=7BZWm#Buk6cr;3hzi1}`Uu+Z* zvzbYDt!dh4^;Xw^O@9emZ%uO>Tzjz%uIr4TnPgYA`F3wWveV9!>@$&M1CbR^(^vN1 zkgl)LP6X){`Q2==8SP(?)aFG9+P*Rqb(n`EJ_M<@Clsh9NLyypgOQMWej_BK{w{c(TNze&s$Qd{^G%5sfUtvuR02C0!H4Rz=O4C<* zgBal`%E_oHl=}+hRntMuB9d!ndV%zn2a&!aNeh|HP|{c40I?%Vi4$qZ2z!$PVm8xP zy5DH~%EtF>UwO|4*Y2{xbzdWB`pShi-|o&^bYEfZ+(n)NX#;8d%1Jk+>npTLMS4a4 z2{zb__Nho}^D_{%ePt!;@G_2g4pMDTC{SCF_K8goYC!7w{gF@=&i1^#cIp>I{;@=w zzA_O)Rbe{DK^*bAq(7L0G~+hzE7J*T2H;``-5Y|qudt><0L27xO@mQ@()5)XAntY) zwO5x<*u%bP?M5!+nJUVm8xP zZZJNpx4QUq+gGl&!L>Kr;JP~yG<{{X&9^(_i%>DrMf!r|zCwYteWk_C>G}$7hCvPC z&-~YHuo>-#k<{i}5v;11xKMqCI($d%{Sc|PClshZk><}Z>A`MDJ^ywj>YVM=nUL1B zM4G;`6trp$q9ajXlKx;V(u~`=#3D>eT6m62C$eQu4!;Dpfr8uIS{Wo zigGe)3gx~+dDW+&z9y1uW_p42l_N+$4%XFWu@*9$p`@==0#PeUNf)6VNZeN_AZ9c7 zf`hlD^VuQj);>FGgU!@TliEBBLF=;xD04BDTL!7tBL!+1(q6LZ!AX#MerqIHpKU{A zk0sLhtQUmpcbqa&&v-@BAB;xSn2&unkf1XF)Ns(G5X3%XP3Hr+oFJ}g&=F7?pA7~v z!BLcxQBx@UjPk0vpzbD;Yi7J5K6@JJFDGdsvl&W!wgbdxQA%93`5Wys3W(W^&z8m#S`M;xr)@Rcpoo9(O zJ}V2MdJ?CVM7=}$gQ^G`^RdrPC1@*7yB(Alg4k!Q={KZip~X_uAQRCvK06&mZAVc~ zMoppYGs>$j0(B{oTr=Yh@mV3#i<7jF*$gE$6Ta*sPlkHmCpdX?^C+f+cXoi;!wPQlKgzt%^+#hCu51^dIW2&zeA5V2Lz7+W=bi z12LSak)%J^i8NzA_Sw4x-3VZggT4wu>@(K%IDj<-aZQ7jfYSJE3y9AhML8KYg|g2m zuQ~!s!GcmV;|=lIDM+tIGAWC-@V`fmJPhZ9XcMKxXY_v)d2FPBn9caC?Ct4%M*pK- zUuX0$+9lX*mJK$ahoJS@b0~8Sm3uc*tw##fW~6;&(}Ts3dVW77SfBlf$WcqA@!5C? zRk_PWR=I%efV7uvH_Jo1KOEF91hLOp(}`$p4i2elPzg{PpEUw;v7;y_qoz>y z8Rb=lpoS31H8b9j>+D*j-%w{O@*%A=TqLlcI-tgh;jDO6Z&1QTyeqK7C@&8ca zSz-ROCA_o&dOrQ{8|$;KkQP}Y zjnDRgR+B)?AZiQg4-O&Cn2&w7pP&Z-Jmnw{K?AYRSkvoB{g5E8X|Mws)A;Or5Pvy} zax!Z4vCk;4ItA7{1BcYictdOv+*{WHv*I&$@%?AEm@qD{JcOi~?dd9o(XY_K`~7NYgp7L@rRm3tCWtw##fw@CZdrUw-v^?dpjZ|k#C zcVPJ!hvZD-vw5IZ9*BIR&LaK6V@NaRW1lS|s0)CEgPsdP>@(JM4S-t-;+h6C0HyKS z{UDY*igGe)3T2;BUiB8JtweIoj5ow*-yr>Pk{136$;kbzH0)mihprKoB|eM(&N!RR z_-xNz>3l}NW37EgKVz+Z*31T*Ux1+X*$pW3Rx0;mq*{*@sC$w2s7((#KkxU{5@~!^0HOK{rvpTFA^kxg1daLFXO|I_jfR|zLqmf@5c`ZZ)dA3gAg*bU4=9b# zI)fPCD9XvGDU^LidDXR`ZX}Xx7WLUeq(70Qh0JCsxz5&u*c_$AXY@1dJT_85%w~Kx zZ$Ubr(YrF*XY?MH_8I+{i3FR|Z-`i*HJT4g;E4A@s`W^L>WH-7Ha#eU)br`r0Iko) zKzf}e()jEsXte;u5~7BX{@?@zjrrJTC6S=k;`FA2P7gusGuHG4QV$ZuH4P3xdm5kl zut`N6nxdSHnnKxUlvmXQ)tE@Gnem2PXYG-GMUoc&0i4KnHWtK`C?&2+`r$z`n^}LM z_v+XW^;Q=anBbZbHn{d`8(cTd24C)mU^SS|^XhG;vpS4&`4!NBeh^T6_{w+f8qQZknI}F3CM%6VG8g)yXJSw(+R@v1V|0E2HCDbPE=zcyw(Dd zeHOnvH48v2wv?&qKMb&%RS>>rfruK}uEFiu1L8ZPxIMw&)N223R72NGwrg<3OTiJR z;E;+7swvs7!Nul*$R{eKP*bv9gLQQUQJ7wrY}a62lR(T!uS>RTkdxGdARe=nbRp^( z+?VKwnK%$halNb7BG9eHXRe;pX ztt6NQxiPWyt_%p(2%N?ewSe<$yGidVOTcWL?o0uscP*kk&p`MB0a634L3$TmNoos( zpI9K$Eu?p`n%_YDWhqnBe^6ER? zm-H?!aWJs4P9dY3lHSF&pABMRl0r>M?_yogfmokjm-H^ywF|^I>2*o(A}1*i9V82f zb_w?->KM`96-n`Y>b*YgIP$3^pI$JK(XwmZ?$E_%?3%}KFx8SFMt(z?whXCTL8Nxs zVDxGDQ4l)mcTej~=GaLUeUc zgO3)2{Si|WNlGo2*10B*5oD6$3h4~jDs>-axPXe$=6#s0zKW8$J`{puFt0bnO1AW8 z5kgF*RlG#687TEYSVhE^?}+0o8p1Sjs91zv(hR7;fJ4*>)Swko*(};2MPd(nJy>9V zwNMKyW*ne8&`ZPoj<3AvtLwLj-w&oYi6b3r8z} zNR>oSR%G~CjxW(ubTp7?c^$1F(F!_RNum{Xw7Nu3)zLhOo~EOXBzn4zwv_0ZI@(5} zXX$81iB{6l?h-v)wK$9sFsGkHtEdY(I#{A{-J($v&DGJd60M~!;RaqU(L9xfXhzNy z`7gXZ&QbL^K2^u-sY{?cBWIe9H&DGeK10V_&`-NTe!GshQFQfX3f1|zwbZ)#FtK0kdyowTf^&qhX`!uDl z#aeoGp>f5O*Q@Uf;A1(Na+m6L#p4tO;Po0x8s#GGb%mn(s!9*znxO0^eQ%7@8&Nu) z(7ma@>Rg!_G+3&BB;{d~vI?h(Ly~_o5p>l=gvZISv586tqCGMm|ps=ROz@!Ol@R5?)9Uj>*B|;^Ho!#?9CvcC`|B|Gr=(71``*( za|o=}4dT9|rVvIaD4C9ru%^32)3a7nv(o0?!NqD#zezRUBP_+De~NIg5gLp16pNHv zYHG=MqlnR_2~wR9c1A>cQU>>f3rR|$h#w0j>mU-ct2jSJ(aavsR?i4`TN+L`Zln+| z5W&{8^$b{@#?}b-5n;Bj5n`wihb$4!{-Ov^eAHwQ3rC3?&Ltt=_}Iwo0l8=OTELyY zBLQ4Ts)4?>^tzvVsTyuIhh=M7HY2U4fg*5 zAO0^mjUPM0Yt-t-1&`@*sntzXA2Uw0njtY6ms;H{F&URy-6FBlJifHLRbqj}W=gD_ z#AZpXg2ZM^>~x9UCb3Eqn@jh`SWb0`&7*59mXl{X?CIi#WvDEB*x2_Tw$oNhwzijf zns&}ZREYY;Fy^mGR1_0S7-Ug=VF~AABq4v1(@o$<^ZPm$78oQ8M{Up{agE0mgSb(B>`K;Go zQp57DRvuPxyi+jV0<54GOXxpI8V&UO8Pa!BTK1;mi7NfFh7e)jf3A3rOh32bgc09= zt9X+9cN(JDr#V-#|2WRs`Yb75mZS7OC)0T@&e{4bDes)3*9rUeZZQ98J&^QnBJ)(4 ze)N{#<6vCb0fCb2FO>npLY61zfT-6U2hvF;M< zFR>mH8z`}!5*sYBUJ@HAvEC9JC9yvGqU=4H+N4&%!t7C=fp}MQr|CUqJ(5+n-{dJh zk?T`wD^g0)Q1Ced#~no=OXhfe8(xOF9#8kKs6lA8!8jAV=V zTgLa4R!Eh(PbNY}_9@Sc`dC@nknCfMsIerYW|=HcQhr50;ULLAjRqOAc2?}u4Ix7o zzhEy!iv49kIhauiaY~_aq1b z`I$7^f1Sz8E+=OGWyE(w7n#wMr$HDIHjD0xL}5d38K7 zi7^>#m+OBw93(Ex*t`P&!1ih{F@T>WFqbJe!9_ALxFL&?$z!yQmTtw)E$pAA$~}uW z0dT}O{s715Zx;#&WU1OnY-0s-DNAp;N0Qau3~TS1De6K`gy3nA|0kjBmpiMRL)mG*-eLsV-nK`fYfn*na# zObF*Wpted3AMPbKGeA9CHRUdvc!yIC`7qfUhkHIT7|}4MCECS)hfgZM`XxQnjYowRllc`jB=*e-qj;D^Nd&B*i z>O4qVIq4HLGUah^EnJaF9qRuT^qVu4fQ8e z*AP_`L_?zZ(vg)#)Fuaq)XfP;Y@WWBu_Z$ldw_1r&+k! z89zLpsn&woo{qbVI6ELtEV|O8HpNm?B0rdrI6LE7+zRA2*~E;P(Wn_Qt7oXDtMDrr zIO1)2JkvvIjSSTpi36;_^)h{fOXOy#@eogQNJnV!e7cQjEj2ULLWm!6$QguaX{`*k z5|WKhT0JDKouNK} zG-TjL8iOx@ux$#^h=H{P^oMYm1FRQp!1L)AtcUI`vFBfsSAf{eI zrVXU`Zd`!YbRWjl`$+u83Q`?_Up@RC;>i?9l{^iu5dq6C86jxEZ=S!w4l5t-F z@di;ZvJo^OU%FpPz!wniO98%iqf7?OT?&WR&|38$Io3d*nnO|QP4=USvlRfK{{IO11^yZsyn zc%W+n;YAh*4~L1lOz}Y155#byq_EJ?nwZBF-CERi5VNc$M6A%r;*Z!#tEV9ZKlpD!gi-mspZDlcT=2)4f^hv~~C; z931g`*#cT{UzR!-i7l-_mK$|{kjd(Ul%XexfkZt;v50+m`;@nW(x-r!>2!tdb3faM zmbTO*AfB?ijC~$pU=^v^1mSk4hBA5iVwy)R6;nR~IpVOFk=64*gTdr1L;Zv-ss$_~ z(TO^$AD<@csD6Ah(b586mo*zJ82HLcqSJKmt02+oT3Sh>H|c0~iO$f`Jc-_#^%|-d z%V{Lh$Fj)Xv7D9?eLRb*9m{FcK~eutj4Y|%hG)0oh`&u1!EKTSV@j&8ka)xj+;Av9 z(Ohv!ReC*kJ>w7s0bK?W>30i5XIXtQJ|#O{#6ZYZf{fquy4pgIR%nv<#cjV0CdU|vt+ z_JveUFR4C)cwZ7i&s|2#jFRdo#HC-g&HsrCq7lR(x0F<8LR{A&N0O15B~>ekFLTH} zSeFnj*GT`nr=(H?ARq0R5_Gd|g#!cEqLOMFB)40s-Vm$Dllyr+@Ho1)Jr3jriv{dZ zO+DbKEg(K|)Cp8nYc&S{5h<~RDe401HxRK6XnJ|lEd8vtDjJE$%|{${I*95?lrHg6 zN1YGi@+c(=HTsxCM*y4PP;#vq%bsx5JP=D9WxJ(8pLFOtU~f4ztZ=!bz5;Q;QKV2W z?I%_^s`N(qKWx<(oGcDmZ5(1R{U19Ms~AuhK+wSogIBhpRZYaZYlIj8>9{Bnd=$dg z3N{nS(j<&qPcsMkzXV$E%aUO&;CEdH>LwA>zseZ*o^OHuN+=JGGFV(7mE7p4<6py1 z-{H^{)ln*{(M^nU7itWwEupRpMaq7|q5XkflLig=u@Wm$UgB-0pM4L#aW2TaEsf4Q zWuHboa7)#7vs~QrNq} zJ?_{Pm0t@m{W0kHITIF70zXx~FvgR7yFT(6MP;nemHzWK(gmDOJrwD%%;RO(M zutFI^biuy}F#yuhj^LZBCVmy-CP?R{Cw>#+F-TWO3Au{3qTdDE0^}2i(Y{L4mOq8~ z1=7DA!6Tm5@wX7=-c(*C9NJCc>MEX0ss@l25Fr$_Dz;+0Cr2sh$koncG5FSkdsyg80w=prq5w$}#2Q+}NSqf0Y)u9`NMHYy- zxh7L=jL9Hwu#|CbZKq}tgb$|xd9ETaL-@W0xEwk0M6R_OHFk`bsLwn-n5dt?9wlCG zgJcfeVVF9Xsq@f_)ybQ&c8)`L?=aQS>1qn19Z^n~G*l~WI z6BDB|+9FN9m>ZQrt9g^izF3YZ(G`N4?<#LHCCtF$3mz|(o&w)qLQRKw7U`o$KD-_y zCCw?JD4$w_({d}-6XffJnagXcDi*{TeGk|l7G)doEJH#!e}n%Bc$+=Z0)RI~iK07< zq6}744waSK@B&Fdy@yX|Pab5_%2gTp2=l^SrNp9)IhemxerYE?m)h1nn4$WE8Akdh zeNU~^&3-6DO-AAZE8rPk(#gO}GSuS$UvThL=rYoWGt?W9>~K<^>By3N;!$3Sq>8Eo zILSm(k8O{$j91A^q4Fo-h|l6$%9?#*naf-g!h8z^^MFNkt#D{pV0|oVF6mfUT9f$_=BedIj`E7W z$o%{VwmvTs6n&XVmoB!`mP>d=UuV*-1xpj<3SDGWxgrzE$k`$rd5gZuq^e}(EQ^U6 z6JHrCSL_w-%_RS0+iy%9S+p)wU9<(i|A8aE7sVS77rmURu0Y~!D+s7|(iJz5_1uXH z6xZ|GKyPka(X03-<^kk>%4wi1+MY!l_`3S;l1>}jZXe$FetNs?kUoBt; z2YTWw+UBU^x8g@2aflkBq^A^ZchtEcTBfIVII1UzVUBXo@mk^g4!sfB9EXPP;YA-Z z#cg~7#EXt%OUN|6=p&}ch-xc{-6_;quV|Mm?-1mFT1G!&6n*S~Q_!K##u2uITo6T{ zI4U2+rH(pC&ZRm?|J3|$#}5ZP+41as=CwuSi!GYzs`*;?J(74X}XgcQ{PbPbkME-dyYs!Zz^>;vP}LTvqkd0 zrPOW6x9;EMjVO3qsV&Hy`Tl=x<$r4VW~EMnh7SKXEs+Ynqf`QFmi#}cay2!c*`m}7 zP*~=J|5GcSzGH^;Yr}~hN~uaHrIst{A{u`6eHE#6H$t~kZ4j1*cjUyxhfbzbK5{9w z<=Gn7naN*Ea_w>{3rS-;D$PFwC1~Jd2dpN!~vg20llEHhXEcbj{?X-MdO#D z7!`D6=h+d8&6GX}`!RQh~uL3rmP#!s%ilDyJdOxryqgsuV zvYo=$L2QdEG*`=UG4&NBN1T-E&)yDrJAodVOUG1c*yU^-x>}Co?F5=TKBmqE(>5Kq zcscB=xge%`gBjtt{#5RxgxFc$#1XtPA#-l%P*w4E$ z|0aay-?E(|aXH!#<~yp#P}G3F0HMuLi7qkq7ZS5^(TPAVBrWZV@4q3b6_rMiZZXvy z;?8N12-iKP270|5mWO3uK15|BuCGfdJXjc|DGd~tyfI_Nm($YgqqLDF;B*H zy<@5o@(uboc_W4QiKz+5{M5fz5Yf^%re21I-~Vq~M3wA$N?Z|B>NpIZ<#A|p@KCRN zLn5YXKysdw(s*HR1VwxyQcqN!K!{@f{6s&{jQ;h8wRXFkAAY}iK#gt z7Ffz$>!X~SXCYi?fnXd}gf9cFYb>MuNVglu zTvY*)M-*Q_k&$YG)72J4*Yvusak@r*`_%JEi~!8Q^u>p%9Kv0S+<1roI)z zxhcS52KcqGCm~#s0{p=M&*V#8w2eeka;ktwa#y~j10ZpiPdI_HabsGc^TOoIF zS$g9yA({$XirKk{s5O?=*9>30-4o@5wO{Isw?XvcZD=lDxt1FR2agMFSZT~V9`L?U zD=F%7wr%ENkR z;)trL<Ne->gnT+F3STnx=)@R2~GaqQVHVQ(Xq>;50-8 z`%Fy$a>uc-2)kE34DPl6$VM{!s6GIE^uK3_L<32n!cGQOeh@q~odA%fdxrGrj`o-4Lbr;!5IMzbsP}Ug%^xbCmqcB_ z;=&jCgPN+^fw z^~CqagYv{txQZv+?A_hK_BoVZAuxt|g{#dQc{BE5yu=YQL8NSaZH_8$hTyi4Ch8gNe6McpZpaqYBN{auC0O1jz~~O?nSPj~z#qdJW9S>A29s zMIjbKegKmJ8|vyieW8Vm!pbpqGBJ*O7Iq6QTu@W=!bL2yaFI@67B0vik%bHD5_%2e zDg+0RN%}Wjh+xiuODFzDA6=^B!<)+18aOESEo8X^hs0$N3l;YloWGH zwomUhWb>}=Y@hb0J6um!`7$-P~fIR&TTYN6^uW_4!2( z(*hM#BAo3@3O&hZ^J8eSKZBIfgL}6B8^B^dXY*Sb#Xh~PQOqVR_K&iZzO~8L2KLYw zin*?M>la4N_TMLE6oeu8ObIB7&G*MMgj2ZKr*Jm^<8i#)J(9xHN71lDfa2clI>rC&Rwj}qY%#Kr}u0&2}(m( zFZQ=k73q!AVordAxr!4Rr*A{Eee!LwPhZ{*$sE-Ej$g2J0b_XKv*Hvv$2ctK3=YdV zlf!Z@!C^U<@tSkK|*geC(2skLBYN`PiK<_NgT9k&n;hK{}ekY$glEoNIrg(kEkpfJ1ofW z^6`g!9FdQxEE+p1$e;3|W6?w{(;t5c`L}%h<9X9m=Aag8ZFF!74@i0t!gxkEGK`#_ zH@N+JOd2>iq{6&kvA+(3Kjz{?s_%rJSxA^nakB-hKTDO$I*9i^am4E%!IU7FhCNcA zk>wyg*UG#b73Ud}OM0;J$|J?94S>!T3ht(%+mJOishAuCYMLYYmp>zTEse(*e*oyS z4*%o}Y~hOFwKbl>_!gj_r^Bb~YS$rrE}DRjU><>;$at}!B!fKxB^-E@E}s{&0A(>W(E>pU{8Oxeng?%@%p0G$a)K8Oc`yeK z#SdqA-jGMgJ6O)hkmyos26i`PBov`TR;YKO?tN0(m}=tb^p)xxr2S&k8 z2<^uqnSvI`ik}w&T@?Y8`nswLX+29sezJWC|E&0hRNN&Xx>-u}G!hkiNfAS%08DaF zMUrdi2MgT^-~k6wM*Z9}#Ak)P^1KGbt3+MGjcp=D@q@0XK7wG6Rbg_U>~jABVF_4P za!YMx(P>C!rr4RMSwh={-y>8*uTob+!uw)|PUIiHlDzbfT=91vgsL0mz4lLpg7+}@ zk`v8!p^9eqGt}_n!QNdhs&STK_`MZ$%DE5(N0G_%=Of6^a>H_q@$0uYGd8?{X2B}B zMPh9@=2h}a1S9bCJf61?nJ^aMSGg)&0tB5!VioDf9nn`rn^qr=5zk=h` z(I)jIsYmybRNv8DkM8v|)a{T5bV8bm({<`m{BGpq?I6{)o<5$$xYsu*iC4IL| z*J^%ZHNV$F;U9i%>o3eF!c~Mitqz4p2#i$V)8703w+=-AoAe1L!Zh$7raGTVX zL{Mj!YflT;#dv7BlZ13F^UATD!a7b89WO?7h?%saZ=?x3iC`N(4TH&(xh77R#{6ap z3X$9J5pL0UG0Lhc{-HIQmYyOdoMY3+AUj-hx}@t;t`>WABZ}-{Tw9Q#hEZBYO4HtW zhP^R0Ie9rJFEYuJMfZ>cG4(77*f=`vVx`_TX;P-H%cb&rbiYJ|;vgP_ua*X^CuK_4 z>0PR{ItAlNM3w%5NE&@Z9?s@rI-7^eVxLA({6G_i&1|1W>|+14L1f@ce0~<^Vh$Jk z6wdZ<#Y0xHpMh53r@LTGJP5$Gb$*kR}pi@ za1k@c%QaohzxO?-s(X58@!sF_eBU46K2O)yIqzGiPQ|XS4)a}_srn1LR`~hC-z#Cu zF--M|q^cs}`!lKWMBio-+;<|WL9(@okxZ5G3^5>kVaUPR3XL3>~wfv-eK z_!L5XJ!(2N(`GP!r7({~9M{{DFYBbARQUv40Ai00Q=7T^H`J)C0NCn!<3yWc!VS_7 zZYQB8l4(ECrk$`_zBz23AV`|+q!R|I{(b6YI5MT}Zxe2kvG#ie(;Tf^@6r-enA(_s zHCM6TMBQ#E|AcUIK#&})fgb|{7X)~w0p0!*13WEclq=!$bmDi0fwZq**!lsji`u`0 zZM=3W!`($htIlQp&On&62gQ(R`g5eQ}c#ssxGE}sc42Spnj8t)Ff(Z z#v!Kw`wKE7dKqXWpXMWa??zm0oE5Rrhk*M6@`%2-U@HLGDf4XomO-9M=ctsg(z(iP zh@vrL^e)dEao%W`WB!Q#?f-N+4vge@z7|QpbUI=XX+i#jm1*-IqLO~wbi`1V@{r@J zL5>%`A4D(i4@=ePhp~ko{!-w=$cPK0RI)CN=0;oK!WfmT3uC#r9ZT6N7)OJ#l&ymC zZ-~Sy=!96pKZCMV#Du}3xC0#tpERFF@Vw~^Yoe224@W}A6Mowz)chc!#t$NnjUNej zT}$-7YpBuvoLdJ|^P+_RlJH${FgXg7oP__SXdb+dOvckb;|ag@rSxYr!i4|%EQXH? zCtgg{Tgvc6gqXG@WIW-24QATEcsBVr&tX^ue%jwHsd@-AwTznS5;jDLtvX4Yzn1#0 zqMx&p@ih_>#RM&A&DG>@mH4&msNW(XH3|QdjnsT4=rtP{|3JcWw-enDG~qvRC-sbD zUlZ|!UjjeVevQlMZEq|RVP810yNLcJVXM2zXFTmQp775GGwr`1{McNkx?Irbh2LHH z1)Ip9CgCv%aXOK-^|n#pMf9`pXS_s0qUZyH<~>6GBND%6JN26-qz2Q@)6{$^=#nQH ze_z7GcM$#fDQfNjM|Y?v{$YM9is_|ig}er}WBT?_afRXL&;EE_EEeN$jp8q-!bp5s zJ*Jnrhun?w>i4UuuL+&NL>1=0;aTHF*1uK5h9Z`K|K<*Hq z&V;COCZB=F(t(--2>u9C*h`uA%0Y+1ANMC?CJ*j5z>#6uyI62znuq#Fd7-RjZgSiN z=uuMqHEG50l5erHXvi2>#L3hD!kjPfrFr9;^k98-BWC;}M6Z=}e$}HW^u%MObBL9` zOurZ4V>k+bz$;WHIrS>!?k>}JL;qTUxeL>(@(D$G_yd>fG;V%C@GFV4kQ@)9>V;|5 z6f^9M0~e=8h_&M}FNLEN@t6!^Oo&}U>Xl7wN}^n<#gcI$P5^0YHnC*}F-M3uf^=(0 zv^xn^+mZR$wzqs9agd{*QpuC50`X5B8`VC)^bTYw^vcMtIeUDFzbSK zY{zVu^s#k$oq_d=M3YgD=^-d`!Th|+?OiXCj<~L=q)TsJB zDs|6+!(-lwOpw~V;CJ+3qlNgl3=FsVkouk&PExuTk@`W!BdmCE@h+aGl5rWlcp8_B z4t(9)%5hWs4a#S^8oA$Gh1$9qML0xo3?)U5r!$9P_*{u0|%mgW#jEHp_3J^L)0Nt>4$kfDU>6eqg_2G|?D#U=b{y{_FQT|akCrx zw*ySJlY$xRW9p@1T_^RYqVq~&3z&LRLjFyzE1kDT>%7;?#dLYrx{+;nS!T6v&Pmm+ zOD?{QTDMZEp)yZm1;kPvRqCM9soI*Yk1{inK@pC^3K&#wuc>uCvlP0ufnKYU zgF2Y!?g#i}K(OTrX4xR(`94TeoQ4gK9*Rfm#gPWb_I!^nTd6r4%q^!HoTP=z?M4(*LNlAqV^qeRSGYNmO4{ZDG4bApVnya8H2 zb~xn?Id&M)q#Yl5?aiIYWD7I8Bcs0ZPBuHCdp*!6IYni5xV+wMUK%%FgY`X`4~PZr zka>LqyaHUSj3bJlO`KLuV_+?_aJl!wsn_%b)|a??Xzh1ldU@D*3b2_t^3Rb6G@{uE zO&&+M36wQTV{?>6<9T%lD9MkcJPql{i$*a@uaIHRK=PbaXdHj`?o+nD-fu!d9QL=bnVnZs=Bh)cgz}Rv`f86L8vI zRi9>ioys(|KsY8Ov2pCoSM}9^)DeU}QId>V$CSBC%#8tST9oNXUj*i^1L2mC#5vxP z{u7WM1mPbciH>QWdVyUP(+U10(+@%WI;66a>|SuyM94bqh?sW-4y`Lks1y4sX0{NfTgVCXGqAqNX12>@#)Mh%$e33hN2%PqWageD%(h^444HO?)?^I}gcVwO zAq@s$Vn7O4XhE^g$~1hqq*(_3tM zqXWRrN^aS|fi@~vJjAkp1Hk*3_9Gd~UvMnD40l4mE5L%){9UXmTYQhk%~uHiP2#uG zvD`BD9&z8~Aa6DAT=Q8mkqL8TmA{)XZ^rpGSn>ToFk$A7k4~87lj!<53eS*AKAV-S z0~izLF#wJaL6+6cOEO^&V47Ya^bbiq={b^2m_nKi!n`Ocd%_gvEnwXdWjb>*VG3yn z2rq`DtO-*{pMmgmNTOq9OqfDVR*HGGaoAd5CAs-fCrn|T2*$|)%Mo!c`XQScoiK%2y>iT} zgQJwq=!7ZEj$n1qW=1DWVU7W7a>&e@Fokp-2x|h;f1NNT&C}q&5>1mmVG8qGuzm@d ze=}hUy*9>s3Wu!)H(?59+5+fCP=-r5VRC;mbHa?sp3lUQNo8A&znfGNn|TfK|IR9G z)tKm{GNfwE8;hfGxJ)WzBa_N(0E#RvdNbNxA8ItH&8Iy`ohl4gbq_UFSoS~D7uoi={ zEMPf;PAWp!1n_|@f=((zcnRQ}Sp=O_gzz1}pF%>Jlgc=BYEz?n%&Uu|aQfd&D#AP! ztRC6S=%gadv0zQfW=1C!VO|f`s%&O-QW55pU_Bc$vnCZGeG0-)0qMU^Dv~A-!?FPm zt$@fLS-1)lW+$+Ehs?j3RD?bm)ENOiScM5@t_5%lK^ZRLq{1t_%t<98dp;BEq>{`V zvlHpx%PX~#(u?e???!8K&&nsst)Su{SHw|xAKNFbAP6ZG{3;2%u#Mij!_>`ynzkrb~bZ>qo9Sb%FdHKwCK#rWx+*n;8hMV4CXR zL9%JI+!b(h3FW>S=-mNBrWT!FY$vaNl>%`N{L?w9gv? zvuUKb!d$sWarIHC7-};srU1(0a1>Vgf)(=#E9O+Gv%WzTb+g^aS!`w_irNi70nlJi-xFe`-9ntrhDUNR%8j=(J`T){;aBpIpbi2g#j z&kl8?xp2xzugQ@#BNyoS8rk?s$ zomYtesY~jfD*x)O`vW^o8<+BDA0C&Z zKYyopc3S@$*y%P6QRe&p1?rF5IbQ4>O7HA6?o{`X_4D>2>L*k0?6kf*u+!~uL^JC_ z`Puc8sdsi7zaH4hs-O1`Q9qe_XQ%a1^<25S-C+H3^`rdk`pMKgJB=?2>@;mqs=YW5 zu)Y3HAK1Aov~$HNu}DAcd7ifW-{}K8--mWe=UZc~+W9-Zv(vg=eo#LT!zA15#2MOu z)Xwozu0!daoyPM5J6ZL^pO!DHelqpWPV3!)oo?L_&CFN%+5Tkeot?&&>$`F_?Tq%x z9Ph5Z{!Sm*8F*+r(>~UEDs3lI?~UM`V`jA0xu;uQm}8mlwRNoAX& zuwXAz;-&?FHX(=w1*^mUb8lPZuBLLq(WS0J?Db}D2~E{Rp4cdtq%s@!GXhsI25FjA@OFTHN7!rrco6hwEQ2*MQjN}DZGw&erC(Pj0 zk6EA3Aha*X=XS-*@jnBK!GML|Caez%<(_UNH&c^vK(Q|J1^}|O|D3Pm%>^K;uM^D; zuw6E9gqa@jMoHY3sktpv;uw_aASOo6ZnjK*P^P<)_z`+^yOe1~sWR;b^mYhuik68v zn{N^P8c@PAF-y42e_@$gz!_JjF-T+yjwcsRZE`nDW6Wp>$C(8kUu7sBUit7IwGS`A zOWe|ICiejo+?$*V)7RiAoXwJ`ABFRzREy|#PwgZRnz&g5+V--k*MgcH2n;U;BOIiO zwxfC9g7|IOiKNzSQ{z*mOlWf8ZVepS?s&J_{<>R?-%J;A!O2wk{W~P-#AIuz_DU@E zRV^>xE>hY>po|V_s6SSe{b#?Box4cttV1JQm9p~6eE92b0FThnsh=aiWOszY9>#Of zzZ_uh_FC?eOt(E+HvdL&kjyh^#lxe89Aeivr^OFb9gft&VM%Lj(eR9o*l0mWya4)eSOcgh0BgsG}+kJ?Bp|ndunH$p3Ay`rNpStc- zBOSu$Wa{4ux;{`G%#zPT&*Ls*_l4GYDr&6fy%4k%%vm?xa&zpzkE;f*WQa3rz>$CEL>!;bMwj)UjS;(r_C zlVSQQ9EI1jB#|+G3rm$T_pbu&(Xy$xftoxInCH{ij4}Qi#4pQEB()ZfaV9h#ysv^I z+nut<_+d;HH?5K66ehcerO2N94_De?P=<#z)E_I#{!`a|Y9bZ-k7lS)cEta!LZ5>D z_n60%Srz(^QWg3wXyswO4C)K4&^v&8{$&U=DzpFz+LfJ1##UINOlbOmI;>3kAu5!q z;${(&T*qYZ9HK&%wi%R%LmFz56=naa>pnG7p&e}xt&VG#`kb!*w+gM&JmxjVQTSz6 zh5oBlg`NW1`DIgoVuc=rtDgS~!i)+{Bf;Xb6Uhu5RwxsiwV*y!CcW$mjWbo;yo)6J zn9Oi)&+ef)O7l=R<#1RUYLXRY|EcRfHMiL%z$%?(lV`Jdr+<&)d28kEV?UXC`NWvF zPH;bYal8ktwrqKbwaj#Y^O@}>SHinwGuEq{z?VaRbAWm4HD@kUT7hQF1HhgPa7}CP zE+j`9W^3L?@JT?ilbyZ#N{*)~`)Eu|=!e10BXAU+#07089?5pK-@dn$(CjebkhQTvIwZ>^Rikmf|ISy5}-E)4C}RC z04GnOFIUpy{a`#1u#(i-tK?+QfbmezkHPWe7c8&06Lq?5EfWb>?v;uN9$x6)IHvbH> z7{HAoD31@hf<|hj6-ee$1UtyCK~wHhJsGJHA$|qehBga0!hzVlk4Q|Xn@w5~?PjyV~W(*s&& zjmSMUN#S#h*b+50Gr(SeLpl;kI!h#_XaVb1Fz#|JR<319m$<`r>856a)U}_JJs;pCHN^TSS`ai*)Hw`FGiC!n~Z94XN2h9Yi_zagpX#5o!Kd`L}SI z{97~^|75>$POY7N?0%!U?1Z1NcPu-Xm$g~OnaZfpRt21^c;9Lx4o_l5m*Xu&jb8q@ zpl)a)gYIoy25tG3EMt(YG3<#QMyz#4Y4VU*VDa9-Vw=TigurDLV1iqg>M~KeN7!_tO$QI z?qWs){PmYO|6e&lb~}UY+UmPT$e}ZgNdXwKc`?cY91;sGc53IUq|NZP88xp0Oxzn7 zWsC)ozsv8IQc#Cd@Q?ZZ@8rON6@de7`Dr!7Hfay5QY1!fkr-tbhr|Ml)lLeEbYo`! zR{P>+JZFC@isn@sNvcMtT#lSHIyJw<*yt>}t=jo? zMWa{pj+1wf>F=3yX(y-B+N+SgyfC9-S>JM!ogKf@$k^@RR$;nIV`IsMQWu^-1=fX; z#BUMQIoUE=&5O}8YAcrsT77PEu+)*nt>(v`6Uf)+%v#|y75Fm;q0B-0!lSsLN|r|k z-o2(TR{qW9z17TknB#Sa&M`kD$F`uMv7$MSfpQviJTW^*p4eQDa*_+mXwXx%AX#M` zn33b%W##w*l>3?Er0g8I-gG(2+S9)qHR7{MeU?)18eTr@#}PQ2vbz?r+KN(}P0=T& zK4jg2t9+~J4PlF(lOajvI`9QEHUoS)3a*RuHn%ib<=f*g;e6-Slhl<)tedf0hC_`fL)$gxV16A z0V>zQrAxL$YR|s`O1)NvWxW3eym83sNRGA8%b1ga^p2v*Yhl1XyIH-rxYCVojRNhG zkSdvJ|ER9nnX7@`5Hgs`*|}Kka4t4mz<7kLUbN~6qlCawYhDAmCyOvXBzzC>mymFh zAk}BfKMr(L5tXgxlMOj6+@ponE@U(0bSia8D~}ddvtMwq@9$L`%~N13bwvC=?HSdE z;|n-QJ)O4Mg7_xXXRz(lq+NhkLs#>>x1f%j8=+oTimS`RYU9m=03HuO_henQ$%e+v z>j*v!P}}NPST|-c3*H?R>K~xxoa#Js4~eW6UHVvqSV^qLQzrJZ#Kzz-t1EZNSdrc=adb-)Ls}7%0yM zG|k7dUJP0L!1yL)Nq%nsE5Pz#RxJ2upKGYm?beXBYoEY;K^bKJ3s}#Dtgn>C z*R{doKR4^{DCc#F*$(7qv!t&~k`l|if04YcoY`p%|x$)L3(O)_n?2Hc?;nVy+J zyO1==G>g_RgSIHhG^FVWt~@26nYCcui^H}QOK-<#E->Bq;<|g{%b` ztc@XS6Bt`VmUJLn#ydmS>tO5+S-e(vHE~zSItWHikD!b#GgzBKR$VZT4Ou7M7S{be zA*%}*XN4>_rps}2$QlF2w2;*-gS9PW6@#%VWbwn1&eryj^)MJug{5%m%82duj4H>qkhOA$~ zIJ{R-##I@tX(1~gj3yy#Z3b&r$m#}0-;l-Uah+eYL)JJjW`rz0W$jpVLe?@cZVg#{ zHr%l;4_RBmcqU|>l#%1IkhK?#uR_)z+z+vt z&GJD9$Bj>LKf{4lA?FOs&YV6j4%o)WimED((#B;!-Wu1h^69Fh4Y*w#Kf}EAL@~k| zk;ph~TgV2PoU#87v&-AL4c5UjTHEvH&c@G>xDwcc=(VEVcDStE&)_yeURdnuI+fm- z*PzW<<5DL%a{(-oh$dX8b~&?@HBKL<9<&+OsEb;QXq>gQNh6)x5}6@B>SxdbFBq{e z4pmDbDlKJ}Gdq5ZL_e`(OLq+?GQGxl9)zGGQ7z0qT(If-Twf(>b1@U`y%vS|8i^cN zUN*9J>qt%S#WRm4_pG3@BUv{U3eRGu2Pl#?n-%6d!+hY1eyvK*cGh^a(CI}kC3}W* zgxn<8tm1UWmq2a$*^;x&#m~9)W#-IDH#_+~VfKgPoRaBy&}4KcDTA0NbA9C4=Dr|I z-rgn8^gc)+>0LMcIrO>szo!bF&WMRm47}qQc$L2iZHBcSW-l=|1s-8!F!3+L?QM;F zG0gDx$AK$Ni{0AS?WevUtG-b7&}3t=(g!i_s$#!VuZ}9sjG5}-*1=I&8$`FuR4JoT zS_3?Vgn~>$k$B5ZBhw$?kSxOMLSXJ@CcvVQpxaQD-U-WlLkQx7@Tkz?EaAKwea^O< zk@NEOtxkXbLcZ166Z-mX2XLD_e5>~l!L3ygx9lLHHOr^53Ic&P<#_+Om9qUuNI;;R?Zq*oqg>O#;R z&MJfK{~@|tP-W;1Fjs#D0+zx~j8!h&RF-!CLDJ}LmG2+N|6{~{l^>`v9|F@$u>L%O zHd5?I!L-*iiQ6-%(!rc|j@^u{(!*>4)J#*HF8|DNK=t~tFU{GfVXB;|Xp*O{Bvawj zkD_Y(qWqHqJQ-=-xR)90)+;c+{7LXoC#!a~nNa5M)n#(6O?_5ZZ2qH6o;4?109@Ib zZ;*0}+-W~03keb8Jq+FM%hXhiMkUb;|6_0lEd zpsY`ljA}J=^H{dm(q)%Jjdd78RoqZ4it`X^@sh=J&KhVpzKSOsUd9F+U&T|b>}wA! zzOt69iQ?-9Ar*|^{qF1Ot43E}3GGnP-hCX_0QNpg@x7)(f85oj=Lg%!(3 zHZG;6F|gJFo-BgS^Y_58WgehWdS}iBYY>@NilveA8@Rtqrm8AAo;m5pu zuvvIPIBd9+lsRlv4u(zFaM&zIDsiOv`j?zf#jCeNJCr@J`0ghn!=}^uxM_l;aIJLq z%we;Unu~x<2=L^+(0P7EC^Cl)y)jFmTu$bLVkvXj2)+r}10kL{Y;vGBFCus&3lE3Q zH^6=f@yM|G1tm2{4#L$S4(os=WDJ|*0Jh2^WDJ`#0iGWal8;GYS&P<|4x6Lkgt-*7 zxdGJ?bl3>t7JzF*LUh<{1@I(6t@Y@zc?-Y?A!zf~VI!u01{gzwYC)5%J?DT9o1^Jr zZ7>>^&AM0y#16JoCop=GC7wiV>97&jC@?N5#gfs&mJK4ou(=OZ9SkiNyTMQQnKl)K6NPAp{( z8^J#T_Em^y4x5vpHt`{ND*%U0Z}D*0q<|e8;5mpHpcb8(xXkp6+ zkzm;D2UQ0{iydw-l*ufpe4%4Dc%f{j&-!;m;n_j{Ny@%naqNt(Jz(R!25??szsST>tBaNjrBc8$nzmHyc(YwerumY0?&&~@M?T+ z_!Jd3l;UEp#+JdIt>qPs=YpvZ^3=HB%t4L|a1<_P@ol};XeH;?rBvMt@UDQ6yb(Ij z=cmE7m1Zv2M$Zu_+`p z1lTMj=!jU+lncTOnL`g?XJ+B8h|BfFC}0yqTsu;Y2PFd`Tm`T=i}0urcvsKd1@OL* zU~54449s%?-XJJ7nOw(;vU$8LCYB*I--7W=U_zfzvaB~kPpY6{>*3J4&`KXBurbY` zZ%<6}u{&N^L}WhFA`Rqv$>dRCFL`<2-}aIPVJ~?T%%GR7LwMh;{1oBaA#&l+DquWX$tU!kPzu5Lg)?f z+>nsjOBOPR3Baai;bAYi7TEP6p503}1AI7(kkLzC1^7-#i1w0i0sKNxYBKp;*}bF+ znyelUt%gJOlD1%U4Ovp@u9ut({YAtipRku?KGGx&3zgrG7XAoFR3&dH^Fg4?PxDq3$|$quq_Gw zGBeU%B0n*4Ho$=)A<|2Pa0$R!AtAGu+`}AJ0J|j%4|~ajz#b3r>|XK~zz?zr8NK9Z zfPaL9XfLUP#;AuwYan?6is`B|V=ie6Mpv?=8V=P>d)(@d;Q0Al5KTwtSYBCqtX*rlC9uY>tlSlIbMxK z(?Y^lgW~ZjWASFGk(sU41=#BaSOKcSQ}(h4d75@;{4j`dy%*Z*cGLy7s;Mz2f!m4v zvxKjAPg*@4Gv`2gK7sQxflp#)Jd`s7AUO!IXOn#$GmC-T7@`*u_4%z>OTn){-V6Bg zfMTmmTd&pk;+lC4@IOfruk`Mv_K;R7DdQ+Q^&c?eA)o8sKAp|)yt^;^iNYHg%E513! zhwpX*d5Nf0c2az_l#uRG@u0`enwZ(+p8EgMLGm9Je%Rxlh4Li=Pi6w>aUVkYbpRy)0oZjX z^teBOBqq3I$rp(F{N#Dqvy_ZpoV4aU^Kka`m7al*O| zj9WsMcogk%_W|7=GMK7Vk9z~?djTWbT%}*z9^)Kldi{w?|QV5--Xc{4|?3UlQVlLaq{j)%puUg9p#@2bN6{Xa z0@^HOFjc7@*A-~5fD!F+YydL?;CK?W8nb)cLV(wXgi<|j1CaZON@c5$rFz^hz;A{W zankj;@LeCwaeQP7lS@)gfXO$~Qc_%sNYeDb(9ZfU6;?5KPd?x>8IVVy0$p2pA; z*pOdc4DC>f-hFL8x~*P1;Fi{2a6ZFPxDTtn=#I+g)cgsoeA?m3Z)8n)HO~ysQt_yMPA@-Km^)zrNz%5yX zj2)HT0AI@@WbCMX4e&n!A$d>=%UZOV>E8Uq%&ht)*#E&{OKS<*<%G~0;3*+N2aLO= zbq;{@32LoduotQk6*(Eej1aV@b#GowF9Uch2~yKZ)}Hh50x_|Z9&QEWnX*|I3+qp| z(_S#XB1=4p*wP&pVdbDJCUIo4WFv(w8$>+6Avmu4emp(wzI<3Dv-_$Xbl<1L?)x25 zX`j8G#%%Y^3%l>1^)kEfYH-%mvHPXd*-j;QWVceY9oX{$o_s=DbPN=k-Iv~&FQEL6 z%xA<>X7?4m+%)We;IMdR_Z@;{<``hdW#M7>?GCJWh}%}xJ@RvCU=+ZKS%i%4dlkUq zEJ8;2y$j&O0U^0t3d>rwnQ8Z(%FNyZ?Sp{o2-DMVB>L{&&pf#RI|2ytUK-Ib+u6KWDAk zg1}mf>d$11E6JB5%`pr3XUAknt;;S&xtvKzSUF!qn$zlB9fB(p|!y0)5v2bB~ZEH`1nzD?CER{LM&^ zCXm>OMuJDk1T#f}1-sg@Z(KIaeU%<{y|mODmvWlSEob<-Q0}s->>K77{8&tG!pin1 z`*O=0R!c0EAAE-LcNq6!ypSI=GRXl5J^Q|9?wc`F3s6A-dw4UC#mcQ>484k()&b_+ z_E{dS(Y(stS)&)t%BWF!Q?&Ao3do0Ut2k4|WZ=~@n7x&zD~VU~ZBjj)aR zO~ir9C;8ON3xmyp$>@wcx2#(V+3dktY4IvrrY1TFB(Y`FV~bF0uBpGVlG##xZr?oYOi8K4n@E20(C4R_q*D21TI3It@R!%a0bWMik7|r2X$%tD zzH}jTwe95-eZ7^!@8s!6R3jxDN3^SaVKXUT=8W`=lbaxq>(oG4_(;!??<(G}6n@-L zziAq=Qn@LtyrmR=%2P8sPP(V{R6ci!g7ABjN%<6}m+&jB@w~MEIKqU#2?IRs_Z7|C zx7jZ-O{sr6y4WHkKXg)GubI=;`O_xd(Y#)|I)@g|jOd5>#rwQoK$LZ34gT_pe5&b2 z`>lFiR^M2MRN30R42&yq6fzTo-zXTO`XFM>)?Ali_Fw|0=bK(l8>%m((c;Gv&B zt?C2lE9*RBCS2&5Y1P&Fn;M@m&ld5frdq`KtlqM)3jW)2-qd(VX=;w82LA)<)upL1 zOAY=9)UBXyl?HSkT>hw07s5!u{-m^F&l(Q?2h`g0gOce7irBq5DIQ_EXw@IRp5Q<_@AQiJ~ibx&#P5tbVK52*1gO4Y!TmKyxG z)SE9j2h?*pM00MwxFh27!J;xgRV4buBs|=EOnxru=8JkGfiXU_vj%U;odiL9@-0cN z{>vR!Z!s{LNp7icyM}{W+#W#3E97RDTRQIypsotVU8-|G2%vrnx!=yXW#oSXXtY9y z*{^9oZie7Da#?P~T6ojz&|^efdee`kgNPpQO>a$y5Iw=0-h~bz+RB^WhZ!PzqBngo zGr&a32`b_LC}H;ojPpt*?ehmN(h^Vj{B4MYd>b$!AL~o|(^?YcmpT(ZzohE(v0k6A zGx{!si=QX`gP)ka_9UM{dS{Gf{=@ za{lc{Ya5`Ez_Zv+YRm*;3}Eqld_&HHj|sS#AOnC@Sn#hEOu3QZ7yRtpcpTVJkI5dX z*+D%6BzhMAGE;uZoXp1o!y5cn)W4KgKgZjmrrsjhV~$CR`eK@7oA7VIjzijS41!NW z!Y?SMD*Q%Mz_v)8K8|p^;bYl+?mOWxL%pUYgi&bI@(w}T=c@$? zpU-xqj|^Z)bi3h`seJSm4JQ~Molg6FqB`O8k=C@&2aeN%ZZ~{rk5Bw1r2C{LOvs~r zX?c1y?en41gwN;y;KdMzOtana*(N^jl#r*K((+(k+UN6j37?NfA>~C3$xFz0i{L-{ zLfYp?q+q2JLuwNK8J$s0{ANxlJbsriGc1TlWc{k9J^i zi*Jl4{5JEYb0AFkUo2p_SyCO1jm@;g6aFHJcY2K)jdw>p;m?L14fF=}-s_ClmiRsi zbKj)Cg@md<={<57V&DpgwU_q&!xR(3)ri6?q{9#wn^A8Xv z{3;6>4*rOi-;|K?gx~sOYW^*u#(zdU;Ww7>*-wdX{)C#I;#I}>sX1A~p%SY89WWC< zL$tDZ^^W*3)TdXRAQS#a3C4BG{6P3cpOMda+GjlB7sF4KViCRVa23NVg!77^FMdu= z>PN&eB}mx*M`|jG{G-P+)Rt+LUE`}BZTb6}iKwK`R?*?{%7CxA`oO)jX_IegBPw~`*ALeUd-)G?$ zGQH$q0d7^s5%q64aml|iu$Ec)XyTH8PhfpRe4v(nJaNf?WQd`^^g*>_=7&zAJA}O> zXH~lPYP-5wHI2#K>Son6Z5jOpsKb(n)4Y@NB2vDUY>P&uMiFN72-YTob&N8pWyV8k@u8E54 zqvFP>xG5@biHZ+K#jQ?MC$~k#?NRXwC#sV>qT;To_-a(#6BYM4QS;p&6~By%UpZ0p zJrETSI#KJYC?4t03!JEF7dcV$EslyyqvA3rs^t|<)U+#|sOYMwxF#yDccP}<=tT8u zixU;y8WkUPqOJC*xGO5Y>O}Qwj}tZRzNolADjtZ62cu$E+MsQJF?L^ZW1D(;Jl`=jCkC#tD~PE=Dx zheZebVdbVy8E4N;m~tJem9sJ`u5u#Jr18`mC)&DlqNd#x6}Lpi2c4*1ZFQoW+7T6Z zM#ZO`s2M%uL^ZX`iMA%A;%iRSv~N05$$O&WyHW8yCu&CfoT#SuJ5kXCQSo3@EIQn_ zf~H;MM0I0{6BR9viYuI`l z15VV84mwfMBDen4j21Xi$%~?5u@jZNGAgc$iff|cdM9eW8=a`8HaSuA-4YeIM#UXY z)U>;tXlv4mitcfu=KDcZ{AX0$>qIrRFDmYjiU*?N!Khf2i1yg1SR55sM#VKzaibHp z2wS4!eF?qNoT=q~Fk!DeFXe?#Jhe69EAcS6yZvg6^q6AHCKr z!UEqj?*QE!Fyz-naG5k$upglRHN@<7+B{+nnNLLonxpO;<1&qxz6rkwVOlQPWUuoS z@MN#EDzJOy@}Hr`K4n8 zs{C09*19|Z)4^NYH|8~=L??#PMPYOWb}1}jQ)lKO+)pJtMoYT<3pNuzEelrC)w`97 zPXk4dN>G$<3p@1@ks@}m+|!x}_i%)o`1F%SLE>QxO3q~t;}MramJDRnUBH$MeHS_K zLd`2rALjsz*uJncG&@b6DH%aCPX%U1F&dZ|^SVftG>b`UbOjt{9S{?vNtHi#@?X~9 z$%~*lY-q_eW^vpa=jo-|9M$s){X8NiWJv zu6ddDo2sqYwJPPSbb~S*sC1)B4OO~LnN3t$tCC)@m)ya^$5JOKcDJU}%lDE^Dz#Va z9+f((bgxQXRNAak50$p4)Jvs@Sw*pwUg(!R%C|^kss89KY(4D(kA2G;ZBX(gYjjmm zqdU}&ti^1?cNb{7* zDUm0TE{9rf^8HUY0)<&lLSMp!gykiyAmI@b9w}k2gcWVM{#^-qG2@?D%)83W*iwJF z8tBuY=AcPD@9na=xx`9*^AKS9a%RJln&$Mi_{z)hDO0?XqfGC0Qdd>S4EsI(&-ihrM)OzurMXeVf#?*_3YUmv}dU}HqMH{I9G9k6^Ei&=b%lcSotN1IJ<{Z%3A|g zJi?~1#X8c8wph7RPZ(*MwxShl!+c{{)IM9^+<`vF28$~;FqiAPt6z$B7Or$e6GLg>Q$UZ9DKs{_?mTqRn+nPS!*hyH?6RdcGimhx~ zTk$6v&L6Q&KrJEJcQS?lkk!__uRve^gUz_hx z70)p@N)bk>*w3sMagvGy45#O?rw=jr01kWhP%H1SJ^fna{H#3D%ImE>$;un8JlV>dtem#;7AsG+`8{amX@+wt)|OVD zBh?;HZL{)amcPTw^Q^sRtUTZFED}%cvho5eKX2u$ti0RGSDUAW|Du%_Tlr-xFR}Jt zweoUl*?8(rE3dNn9xJc5{(WHOTdlm$%C}khQ!B5v@_s9Cu=c;P@)nC9u=0Ioue8TO zD?e!YE92UJ4_SGYl^?O`*I0S0`A*WWk5@e#v->s+zX%a$cqhIZugY`06W@f0v%C}c zSX)op#2;9Bhv8$N@zg#m@3i=SD?ev)@SH(Bb->EI3_nB~PaU-K^QN}QMLAlQ-KL?) zi>&;DIYH!NE5B$uioDXwFPUB!h8y{%u7&as41;HI}jy*N+w*rj~!QqMgV7V?}-%8Vj9Y4A()il%3Xowdf^^{$@)w zL&ZNVYF7h)iWsg2{<87{JExV4an=u42fme;SUgc`wNT#5D=eOCWw&}b%F3%OUMu#K z*mtXmqpkgo7C+YVH(9x{#kW|wg~cDVa!ZSEwem@^Kcru}IlNnprvS`p7C$YfbN+rS zpKj$vc24MH?YlYn>=@4|@syi$`^EH1%+0X_tnB94fmU{N?4X#QL);vDftB4HIM~W= zP8%BIsWP7W(fTvo+H-T($e7O2zgv8imH)8vXe<9|p&$>;jPwSoz7=Xps+Ec}Hxj$VG?g)Uh)* zS7iKVkiDv^hHC@27_J`ID@jkuHR61hF1V_y8UGj3;x#QrkBaAHuJLPGG#@7jo)QxN z3FuYjc@@s#DO($Hul#nzc~}|CWL$&G1_&2cqOFLu??Ui-NnV~~mF?>c@XF;+CnxM< zpb4LOQ4c62;H^V+B|-YT=+j*0gaF<(tJj1L#Fp^A-c+UCf767nn0;&VEb>gWLNw-8)m z<7gijub2_9l@UKCBYu2FyhBF3XGXkVM*QN8_{5C(EX2h#UK@*N<@BM-JDhx`SDP1k z$*XY*1gEL5%?mkExQAS~Qp<~E)yiW+c%qhC_PpdOP5de16**R5SIk3c&98xyf&*|6iHq;f_jppvK16zjRWZegb%?&eZ`=(I!OYUAx=S7&(`%OSA18NX0c z9(9aa3X3b5DNPv9>W?*dLibRh*RE#4#^zZ7??k}}qlwuMH2#P)8+O+)=CW#Ps)BcP z$h{kmBpIM<_Cks9o}}kdHYbDBg~a>BSHk_hqojXvRGABa4U6IfyrZ}r&?gG#09%lW z_dpG`BrN7v0a_P@VgC3a`8HrrM{$@xA;3QX_DP7hk%4(stHA#6z~b=Sx^Hpm{^EXZ zVAwM$g-g#DygjhaS-5n1!3P1mI187q%zk5L1DhY>+V_s?NdIK`tqd@&e)P9)NQWn$ z5hnac0E{+-+Kb#kW8tJNTO`lI%SKrOjH=%&S5$Ivz0iI7RMRzuy6)7t~J z8mW}jiK3QFQBsnoFqT}79w34Jsf}7;OJrcqgLbi}0}tA3o;oqtIyvIODJoeHI`F+y zEDm)Nt#ztd10#3fC}iP`cL!fJ^t@W#%tL|F-v88Rfoq*%^NPt`)>^$eZDa9i#WPuf zuy4h)l-$sYeRMQ7v0~rN$TOB|W5u)S0=6z=`W=f}a_b^yIz5K(-{UBJNIbM)Ke`z+ zLja7(0{bgC8^HV!v}Hcutbp#8Ed5}!3A*ipUPms^3icu7T0_jsK;H`)kHaI+--do- zZ4WgEfc_CMY}IMcuO*NA?qn&dnOF#Ww+6KF&-Sp)2jOuWZv;1dIU2e9Wd@m>=Lc(o=4 z_?Wa2$W1D_n=9-JtLBU*?l0iF-+m@GUU;2nW=&%&n$_)uUYv+!xerILz(Eevs; z18QALT;_mP0T#>w9NBnL2(6lswoUtNa=fh|nwOBksyRW(qH^tc!<)kzpJw)eg8SVP z{!aSM=q3pX5%Ih_$5-A?Mjk?0e6~O&$yKP1bD6+*$UtnKQ|Ig<&&9ldh*W2;_#87< zoX7WxOd!sWiVLFR6;bg@nhnz~fA=3Y2S~Pw zJqf}KA&Kuvy2{&4lFUb+f^Z-t@mVoPdLbYsp2BrF4sCxOH8#7K0@86HbRkKbj+VmG zIGZmA^b0_p5Va|E$HZ%Y*2RTjtql!xBPcW+NrM*vZJNiye=W4mO}C6+&$Pb35zxN^ z^|vsKTTy*UxfmL029BQO)p;{uR(%>90XS?`9ANu@j+%}5@lHVR4C-Lg|7(BV6Qr3A z{`@cvmjbT!-y_Ma1h_sVWcIH2h43iASE7Wl#+IPN=bGQ4=_9?MY2M#D=hS{4ZfO1f%WWunq{THyFc8u_W6}gWn5v zCTLfLRI*%-KM3JwfVYPP&SZ{&7ei6cj{|%zB*@9e`uwvHJ^=VhKyZowBiKRc|H{G+ z3RV@RuZ2Tv#HIU1u;$RW4=|k(2Ea3%7Je1N86o&MqH-eiyz+c@h3g^N*Bz$&y6mpc znctA?uQ-;QTvXrrP|kVVS4W>B`KvtJ-xZMpm`!TDN)$Q-xdA zu4@w&+gfp#Ne}bZ$(3)&m5b9*?A={0Ej6RT?W0b3y0~1|_X2>ymFv2*)nU6%U3ZR( zb|t#*+#k+h0h-59D$iTj@wM7UuZP#2w+l58T*R*H$Bq_Djk1~aS8<#b2dE2^tT<4` zORRW4ixx}Gu;O5*#e)X+I5Z{PS4);wZeB?UGl@(3^MGBDm0qsu z1fK?MP8L3!=`UrDHvn6mh0h7_hk#yxq4g_g07;{B&bs+bW6lD1P{@}Cu!JjwFd5*&kihClE{4y^r3ma? zv+hcvt^)0mkQ(MKi72|>a~1jY$h;1|eq+S;p6deWTSAK$B2{ZJF-opyDDCmQUSh4g zi5hc^!g6h3T4FXymX-AYW$6;TGg!8=F&~Y^?OuG30%2O>cvD_9oA6dXKJIZ1(etlm zI88V^1ii5$HLDS(ea6!gPxwQ@#79DeU$K~+8iHOZ{LK;{pCo6egi{dW`F24c!#t4o zuM_=q)fxXvLZWG3(Ti)5&lw}_-%*F*^Ab{%@INe|CN7%W>oNY5g!%dQlP8?R>?~f< zEB^{wr5`jh&sX%iNrfhSsuKQAfN7t@HQ`T%#wv;!<)BSVnDANM_;QA%pZ-uia>S2($c$}63Gn#!x3+*9Q>PVUXABc59CWQZ| zIk}JGTbwK(g@~sfbn@AXZ*}rHDsOZ0xhn5)@_F0{j;Ee+azCw)51iaz^Z(Sz1K20y zsr^nK$exI&?wowS;s>34f#z2fv%5cahoU?be9OHSi^g8I9D>Tr^&j*Odfcbh1~zk ze(Kq|?kIB|vOI9eZ2u3|jLmVJF|XqeK8~^*MAq$=JH<2wuU){+TszdggjLMOFnvK7 zKvHeCusx&Jl^tO@LrnoTGYgj;VK%>62JEIRT-GLX?!F(`qglADO$2`(*t=P{tW5;} z9@sBgxU5YCulz>LtBE7(|16eI@Rq>ZX5q4Sk*&SHzy@UDvUXu@nkm3$X5q4S5&O%4 z-4x=wc&K|h^EdZG{}3@5J$AKFw@9$v(7zU9dc|9JE-{X6^A)gv6OXjZJmMVdru>^R zuM!T6+k6)gH-*qQB^JrISg=me_YSZmSB$RFmy#fb8VN!=B(b6#X<0y80>bK$#M6ha z%5*7HcSXS54wlXs$DothRZv}7&q#J(1UR2CNJ@~&yn&Xax0ZVgmSl7{r6pTyD}$W! zfggjzmfYg9PLlK;fprgYTWdEny%_}kr~uP7y)|$P31VO_2#W%eYtmI>U^Vo22AEz- z+8kC3;R%4dLqcY?mXIJF@)HogA}P}FYlwH?5RD@!kHg~r-E6^x{KIk#Lc%WqEK$A7 zlJ<{>0^eYgP${%9u3p~lxt=#JzbgO1is$9$eToGXKAk1hF$l4a!(YdGwJA*BQ|jC1 za-y#{TrcPBN}}E`bTgV7;SFDCCa=1^!O<;znEy=ZY8l)FkXb$ZB`b-wv0z%N6>5Afbu zIf4F5M~cBz0S@&tS*jy(??5*y2FSS0Z_R|}_%MNMNV=Hz>3Le*#rHlj%O`yH2-G+7 zPWZXaS$~YDC7$pfZDG7|>njHH#rnK!VfsaVRG(R`uT=s??ac_15=ee&{~;)(5jxgy ze&_r4L(BDhNbl9#qV>->@PW37G*JDs=ppuqYy;Il(fk1$IY?Xh*+1DpTEX?(GTX1I zsROJ*h-=-}Z%^E`g}!Tm$##n~(18T0+rc1=DMhkYI*FCb0WJ;+QZ}vV`dx*vsuZYY zZn!?R17(wPtv{Km*zr_k?}uoguv*{w%CGs_x&8Xv`ff~zOD{`4?O74?ZJn%dWGX>X z2S?$H2#l6Xd-VDy<~Zouh2ZOmdOmAkt8TqqGVWo*{s@MZVp=mT%~SyM0?-ZsYob+9 zdAESEmaM%9jHlJIzKvAN13_x(6g*$eM`I@Z6%x{=v`eoxO zWVft=yc2#Mg!sItgpA{BlbAyAZ9|zz8edOMfuQ3A?TnU8_@^OE`;4b0p75K4nf5md z|HB)|d0J8(Dg5(=S+gBE<0Y(%FyZ$WbOe535YIP>KHZV=8zdx}_7$zzm3(@h_CJ)+ z9M8CxWsX`9{oWI(Z;Bs5P5b>3CS=s;@Eo_Hft;&19DSN$#XW(6C|}oYy4OCC-D+sO z3*zWmRaoZ`@5Mj#EPP+LH30rhrv0tVg#XnT8ev*|v{K^yu}(beE%8qgVpC@86 z{-7J#2Fq76?9`o_rzO<*Q9Y<{j4kjyu*m`leGLfUiWcY{x&c^0gC6l68?d6n9n|3G^TBBRKh+go;N?2`lHuUueFiH z6B2kV@jU7qY@?pFfqvhG)*5zY$P1aY-)IdB#$U)w`~2~{wEfocUl%a0-y_!V4D;(4 z_^7Fb9CE1DKIH5~xZUt4uWABI$nTM*eg57Twk#1QtX=*}7V?H>yW#J`8_+HxQ zkK3hv{^lLl=TV?NT(JFPS+*Oc zsZWyjQcb_{tc#&cIVniV$GV}dfRry8UV5T?9K#%z<7|@lJ2av{+o4JOT@c4NxEnI0 z9;>=S>iLsM82-X6K9-udBz`^O_~fmG>yD4uK#fqrjVywjTSU9u}|@o91hj%MT@-}Dwt)uBZWB{aLa%aS+EvdVLAgj zGeDD#VBYhY4re|570AVMGiEv-teK^l_9CUA3%R^VksNOXYhB2cb&8F7X-&F-26No^ec`5+8>U*U&YnVH{5|B3_Y;#YM<<8Wh*! z|0~9)J97}l^n{Bw40CiSd?)&Oruk0N??i}aAM+UUOVA04<1T~fr+1{jHo}Czt~bN! zxzzNn$+(8tokjeizSQ?Tn{f?m$t1{M`@zXT1`vP!1z%X6!H|OwpGTLT&#{B=>i>W2 zy$6^T#kMxwYj46v5QhPbD2R$E2#8<~s3;gg3}84gNDxI31r-$m0TmU)Am*I2VivQQ zJs#soD`$X_8O-5eKs^Tj_gz)py?am9@ZWpx|3CNnzOLt~wO56;YSmkztE;+ugKt)t zjA6-=`)P_%~P03ODI6y>a-@&Shg^PdUG{Q%qCl)Tj$p#h_ z+c17oH_`>lp8>v^#xyJNuUv3Dp*7;4#7r!_+MRSQrEh^Y(->@HbYc938#0D}Su?S) zu8#VndywBqYr&Xi1^$W6#KLE$zG~IeM@sOX=_N9?5!>ZlZ5?uHCv!f>9-MYLTFiFgpW5w+$jD_Cv*J6M$zP;l-RsC)qaBNZbjL4oBglDVKh_X#uB zf`md1xymuY$EFVXlPJT<(B-7l7uY_P)@8J1%wicfY(kJfiMeUoKdlPg&2@?oQ*o1j z%qQmUbO=_%diujCUwzizET=%ETF)$*-R&opEr6z^dbN2zWmE<{t-dr^@RbH9~9Qr%75V# zYV(yT1VWn#11iMo*2vo2#&Wn_kxh;Q`Bc#-CoyPEz8$7o0NUMH78Gs;St>mSIP@S& zE=Oi|w#h-$QC}adeGl13`?4=gvQLb%FPCdZd9*K=`}|3N_a}YrPij8eTh_+Dq+0pQ zlXU*q!0t*A10^{^85H>Eh}dVv*r}4eIUUSL(zEbpIv@vduftEB+yd%zUoa#8<}Va# zpzeuWo&xbdKk(07Hph1CJ3d2C^WE3Mj?kS|n-$6p5u3Y7iP|i_iAga_8 z^LFzNxoSlG2yaRuCx&f<4hz^$2e@^r#ZyYq{#(dw1riFC5w?Z}22$Xtl)wr(`|coU zaa3+BqG!Mx8_1>2DGO*0g?;Wp$~*-U3YF2E6*6U^YJU?EHSk6|xwQ6wt9Ai4)21Q0Hs9xhF7T$J zmEehhAom2~ zR>2z!$;oFr2{)f0qmaP{PL|)1WCN#2@UJ*9QLn5);baVf1c5ra3;BJnE5zj(kWg5D zuCjk9FDcVEly|`7E1#Mc%0HEx5AF+1?1TRE35^~L(HZbXMjO@)$2!&REBqc7{-_pC zJ!T}*7@u2Afx46cR#aHJ=6*!vYIsvPIdlO21#X?@_bKeM5*d4gghCCppi21vxVgTF zJQ}`8VY*_J^0^sElQ|%vP>-otLjsRd;JK7Qm2A8fMBheaExak5T)N-xsdc2N&#m(V zWHtZ^h02UE4GHw2!2T(LX1d_7mJZvx%aNy%eTfVYT3#9LpdT6FOcMO-I;MGkWi?>^noL(usYEeGs^E|RaTXcE*)tw+Nx)G$BRK+dd; z=4iqB?cC;n%zU5M7psyNP-bowQr7-C!jW8hq)gJrqP)-TM47!oLZLE(S*Hd11Wus9 zq?ACd@V~=d?kZ-!6U3lT&eWQJA6_Mm2BE~K5&0Ut=>X)=h1;FaE_@#XKKBDN{s9sS zHPG-{*%%64uKg-x?gnD)AZP68h;nLWx<~8?<{MRCtV+(oP|Zz3%5->RIXPI)KfA`7 z4*{RMpBbM3356PP{Q(sGGw|H22!07~6p|A&_{uB3W0DTU^5NuzLMs$h;9r5)sWM+_ z8~y?<+k=Ec^}s2V_mru?Vo;eOfPjA$?s7*`d<=*|j+{YmJ#E1~iNh2`UJhSmwqc_S z;y5Jw+|$(f3P>o_V>)0%0$)?$=ac}RWz|*r(V)$q%eD9wdzSFV2)(x`V>l>KtWJIh z^|}3!PmTczg=!S8^_1bw|I3HECFM$FS&Yw+wEj`IFFC;sM}W~fy$qR+f3lTjKJkwt z@t??{P!<2_8I-2tw_}sKT3Q|EDSh4FcqKyV`zIR@D1Luo0ue3n{|uK(H=lyRk%9q2 z79zZ`wH_ez)q;_D6B!mPm))_~?Q*hQj`k&0$<~da@)qcQ3f?pdx%5=^BlZaEWG>=; zu8uO_fnX~Ll=W&@pzXgQ&>kcaSRqeiudvOAxgLn#6~4$EOgPN!b0d%@<3K{8FpF&nh3L!RjZSiy4=7P56G46MS!R3agPft`1Tr49`L&)sB9r%IHoyEp|C8q>!%_HWO zBLiIgFW=Lx`xvN}u^?s&9CQJKG`~jv?vc2J5;xSBsFJrZN^X3YAfNmGoU7 z+-L;PhBvy&rFB27-GHJ#cMoMA1qp@9OgCsqU@-;iQUc8iOE=_d?HW**Tl+7FbOA99 zMve_;Zba9=wgPZlo=Vy(aP|e!Vf#SoU~dUZRBpygM6-XpsB(JJ=WD=|N5Q! z8|~&B^wg)|D~I6hp}_A#DX9{ES}3rY%rT)Hsmu^`v}I2t_qzyw25*ccm+ol%MoXQl_my8B z5IaJi=`@uo{+rw`o{-%#TBSc06X44(_Gl_Nc3o8^$N zCy2oy7ORyrJQ9afVq|@ZDhWdLsEJ6q5Z+FPAD8seIu&(QnQ;$O_cI`&P>a?6e&p-`BGR|y{k&h0TK$!%U9lwO}0VG-E8+vR!RlJ zFl?oqs0s6@t(3_cHIUb8J}&BVg+@@lC5UNca_AdF7E9kzlY$Q2_{3(u68{2%KS*X@ zY4lIGngNs>8ml2^x)>j@{6Q3hj!nGd^hcYch08>F6WSKbz!MJ&I<_Fs`kRTpV+%sr zsPg7%u#gXlV#g83^T872`V!vsG;&y2^6`f{c?SWXYugwZJAi~j4cwrDMm{?cbVqDI z_#%y_ojZ2brwQs*&Zl@h70*<~RAlx`cUErxG%Q{hHNgkh9>~o@%zf~t5OV2BoKG#) zsUBZJA!R-V35CkoQCCQh0-k2wBKHF#nl*{ElS^yASq$7h8aRen6R zNqvpzr9sE{InCkukNU}0!-tom0PbSJ=^u(QtnUqPi#y~Mc!sn__zaZG;a}45jpi05 zwVi#Yt!)jTfXY`+kHcKA3>fpH@G5=X6BDCN z|I>u$N8!Jo`+;!(dX`OJZNmRL%WUd*6yXD0_-OVt8?mM6vsabxMLDJjUjxopelykP zI9p5^HB*1m>&P2xXNk9Htp&ttz+|8uAQEO$~5*_pP|yQs!oWnUZKS9o)QHgj}wSQ&KO)e7`M9g0s_I?l4le$1B; z*WxYE2IyJZ6Z4qYZvPwlac9Kr0dHmoa_Or^8BS5_gmOMNmNKV;ghFM!YE;QjL!o;X zg4e+t-Q?1`d#twtTu7VgO2iaeM(W9>)jy)o2~gVSdQoO~ zkWi@1n11^sF#RAzj)XU+lS}JX$ z2B_gLtM)2HtbjM#_4$P|hJ(WPIESxOF`wR6Wzf4hNGMbTy`d~qW*~-ZpUrTuvmH|R zfH&&NVSF5O9=CNU=yPM4@l=pdsKIobAyhaE!Rz3Q6dE>KyHU#L79vgF2Eot=rP^9q z3biixJv09WV%n6Pxjz{X^K0a4k65Qx$hQ}W5z{K8ARb(_?812uG=s+?_>2Yz*6&y5V%m8=Wm!=?W{s>$R>^gp@f

GJ!^rm;+vr8|9=A?8D%uew6skcPxCK(C0-g7pGf={Nx$ThN7v2=0 z&rg&wjEA>SK%L5a^am4=PiBIk6M$*~yDL+HX8Q%N2fEyylnOx%{^WRf>H}!2+L5>i zGyn|+S0i6`aw}d*3L_TJoMj00E2+`cu$g($lkwxaoqOBSUUmio9sm13`K$@Hl zf_+U;t#fZ>Sm!(5#N}fSg15n&63C@z#Z50{_o5D;dzUhwfP_M2oE59&;aSlA1%j*L zjc#&j-66jIQKzCl-Cf#3rZ)&4Y*O7^zieLx-F*>xG`!JGF0K1XwVR?ocRpn*L9pcw zO1rD&G~XOjwr>lr^}HxU(%{5kG;L63G>n_#1+z#DiEOUu3G5jeR9lq#BS z0CRBbUjGVYhtjb{L#av*!p&js1Qc}|ylHB3ST;Spj8ht|@VQ%=@qUm{sDX1ib~mZ; z83aFoFH&gO=n_FGpZg7IlHZVOsmFAis|L6)5uK1v_5m>sr?$fobD8XPa-K2S&zE(T;SP!E;obJlGa0RB!~OE_Xc)JvEK5m^47t{=dlj-s%XU%a$)WN?KCv4F zhXsXC6})vl^4n8jpIDxp0q+L|Zy(QV6XTfg+E|Pn#msvj-M=woxPrkmf+&aww8!KA zyGjl_2`&2|L|%nA{hVBSy8H|MV3FK}c%NHIncqS15F{vv(+YWKP7rh&m}{|dKG+Q2 zXeXD}UeFs%3j5pu${Y!Tr=UR1VEy@G%oSr0oCa@nlS}LFpt>pQbN5l^agb1`j3c&I z+CjI=eay_CgP0Mk<Q>-wzLbsxn0+*Oph1tb(IqvbVn)K%{6uP}3y_EBAR#{?#s z*{NyoMziN~u6Eo`eW*RH=`J?Mm;ivjG|yegR?sgymKMUf_?>&9z8_MC!ka3SOIP_$ zy`iVP&s|8Fc_29412t7XQeRxHFY+Wa{{~{3S9e;9t9(Abw%>4-O%AQ{i+so2;o5aT zAzeUHg|H>Axyz9qQ3q3ETr8nmCa8#Mi5BbTnWWbVZidvziaXtEuArLRV>RSBJq3l% z5UZ7C_yB>+z0G|8jK#>AS*c?UOWXZ+mk`#wn<8I1h^b~|Gzz*0-#Bo&-jp~rmWT>6 z^H|f5nWDAqhH|T<7k005$06<_c+)?0?~3<}!-KWQaM~k(tmUyD7=oNW_XyJD9gt9{ z6u5+PiZTO3nW{{G)V75O+m*;69XgiO)?P+h?4E0PoAw;rWV`2>m1h)%K8pQu6>huw zBbyA4)si#V55!onk?F(SV$+!Kl2S2VP8WJ49;U>LE(!eSle3UoO8gK@M4LA#<2lcE zPutBP(G$e#!Dy%DpLU)LoR$BZULp<05LY&oeLs&*H&(cuPL$H=A{y50kQRujW^kh zGyFi)@(44lbFF2TxLg0+IKX}g=c#CC@5U^)p!(O zk?e&8pSyxWcY}mNZHmY-%5WEI&TD$HUVw=A;7vK?(lhQadPq(!KKBP@nry*hsEjqK zl1E=h|8I-PuJA@TxwP(e^oE|IJ~xCi$AW}HWt_cgWic#wxpSF$9*Aj6Esxez%inw# z>u-@;*M!fYn!2CJPn|?pXGTInI*5xkrF0@)i43dchjW6U%QVR~>XZ*Qf;ZJAm#*#u zx;OFzgnh0bWex!eg~|++AI|`k6$qXVZ*-GO>wZCXQ`F~fqs#*!p->s^Um+X6ubtp| zM0`ZAU7lQ8`^DN&6!tmU5;Dy}LZLEadEXCU`G$zx7T)M4m)3oU>ZYjA{f#omfrLV3 zrW1^XBYWPVfVAYbQ7arf4VNH*KO;XJk<)FhO(zN@*uJ9~r7; zXWz!h0iAW5fQvxx)O3B)ECC(&ynG_K>jG}yP%j42(CxvFfc#nTY9X~4Ad6p(+J@IY zOph$e=k7zAJYTFQ6sks1p^R5%AgYm@;-3Abe5)c8Vq5T-{wc==<+~K@O~)_w=gew3 z#s|%4=(M{~2AXS|pu@QCOAR#KXR^@DA~aJWe`RDB_p%(&Fx_lU)d|bL`dzk8`sL$oP zLZ$^sC{)H~sFe+&+vU15^X?#KlG5_bB=xdylDZ1Hb=WnBDLP3NnkJJJBa0>}6T~D% zDVkE)6B(*yj<0n-i?nkW*UWrnA2Sk49euX&fU2ACQ`dVNYb^U!q>hmds;ly;n-#0W z7Dl9wkqxL@Ausk9?nYdTd=JB$rX`nd+Vip3QYRN6-shH3=5vrxs0@W-ZXUlM7HO*( z>=x-JhrP&~R3Y>GTsLOi5d<$i#tJ{D!hVPx3U7>6g@%pxA}Qr_=ORrm1;MQ^sOf?& zq1NRdVdj@WOc&ImShH$b!l+rGE7BW=JcGtM= zkyDW`R?2(8;X%(gjj(QQO+fH=eDV*ogejxvn-o#igQ2=cwm-zJ`UYf^{d+`J)y>9y z<<-;7l6{-q>_bPF=_3i)K;2C<^BIMo>nU6XU1s6FO+R7v^=Ya4JFPa)VPdvg2iouv zHr(Ha2aDZlwc#N)jLUz4m8z9)p7uKh^^tSpN|7^nigzd$qdeQF_b}g6v6$Vj)%zWf z#6KzVRegzS+3J{j@Muqyq1)Py!mkbLq?PJ12KVi9!elgON!XqaY?l|)rLdoBy8+;M z+_MjT4vLh^KumXz_n~X#5l^ppmJ%I$7FlXU?Ot?$-oT9yIt^;H0}lx*`xq-b9omRi zb9=oc;%3KwyJ^)4@?yp!e2&?XoK6q3u zC;3|8L+I)-Y`^^i8r)&nfc*k~qS9F1>sbrF1v?JgY9h?cde~MiclnCwx}AlOnd8A5 zO#zIIN9(p%o8Z8xHF-3<*r)gsC|27|$ARr+V%u%UC^JT|K}h*Q;nU zYoL!BRrW*-eb$64OwslGD4*_G#Co@a{;lE7^sPq&zoPAq54wGvV|-Bf95q^`cGR=Z zMjU~Bay&>VREOC$ly=JSDUaD`R+pPYsp~*YM~Y7sa7N+-V-<2M1`Qq$Hd)K8@}uLy zrZ&v|mCtaj;Bp)EhB19Wj4^uDfO?o--DAXe)mn>{-orlj}&ZP0Z~P$grg0GGp{WGuV^fm|Addsp+6hDG_@Rg}2}1pEJ>1YxN> zr~mIzUqs$V7PD>Dblu!Oy4%nEGky7Ghd6)BI6uD6b9sH;jM*I7Wp5AzvOQnWd3Hk3 zbheoDg+Ay4?@dGP2O;P2@TT_U(zTz5jnqY|&s|&)TtS(eK=5`CsHy$454p3;yT}sP zzOQclv-UH5`Bx|TTjrwtHFEC*Zv7p1gfV-9nA+Q;hNSl9AfXRB>5uxS74@}@q=uQX zhT`*?u|d*Tj4dWuzCK4hrSEr0b!MFIhphS&Y1t<4Itzsp8vZe6ci4u0V0Dya1mgH#~n@4 z@gTSefGQ&Gl;K67)^pBQNvWGb3?gwWS4$iH)0X;$$$Q9c2SCT%ARYc(7yjkh-T#p# zu&8wJ3`ax_cyr~blbbGD9hC5#F zM7+;kNSS#cxCsU&?lrOsrx7mqBs1567|5d&gXp?{Ck`5%*Zn2F_TO!Hd)?>J!7_zz z+bQW|1RHc+_iJR6nJzPfpaOd3BoJe$?*FrD__)b?uyHCj`RLJO2ZB_V1W^qdg*PqCNHqwjHoF?}RNk)ZLk65_IYMle_B?Z0U{nDR$%C zu^Y8Q9_H6d?#P`BHI?uN2K`D1CLAjFxu=jO3qeAmuz_?e9>C1KkKmW^MwdQp`K4Ol zW&zi6=!F#Xxw1acyBSC*RD?|meC$XWephoQzMWMzBG(J)ec(+I`t>ZBODUf_4ry{S zNGKFG=FaI2bEhMCHN4S9&R&1ZChOrqVXIn>9LoCKD-;SrLZLRb`66YwvHSkso`Zp= zd-AfO#{dhP+G7Cp%XRTgX>MJlb%Qrn>GPuzh}`OjL6r8n!;vOqKtiD+HE2_1c$al% zFBEV(f|tUZ0?5VHHXHxVwc1qTbI(xd9T3capuiOKpECS9#@c;7)gHZ9TBBE`Pz?D{jy-jBP<~}o%JY>Lo8kVZC)|qpymGJ&KhpGil+3r#Y{X+t zdG^x?iy8o@uQ{Fu4f=9fJD{;*Eue8OVs3ypXz0VU5!^gE0Nj-ExmS=TAqd6-sKR}j zGK71~b|~O81pk6J1(1v3Hs=VRFJ~{K5}(_8ZwT!M5(>2`+$)tK+(-N1{s`)&ND$4kpW#%*Im>S8n`IY6m(H?09*Aby^vS^#dvf5MWxL_Mm9jf>Uqj6= z@CF8Q*!12^Us+)ZKDXIE$hZwiDAd5ZuaNOZMM z*J(jMfd?q?WJ;h~e)Szb;2nB{TG7$S%Zzj$RO)O|_Ud0J=K?%K30L<1hMIRsvqAs{ z%bf*!cGB)_&%`n}DzE75WR2x*eo9i_g;9AEw7hER<16aVxTxe@WsODcUsTl3QBnWY zqN?PC{+PsC^uxU%ylFx`aY2i)FrV84xn(~PJnsq0CajV-`a#za1W$rDy2z!++)3C( zt5Z>*?&~OX2S_MXM%~qNpl^))g)H%IU^GVT9$-4?Ucl{y6AG8xv_Gsk7{m-_a$MY- z!QA8Y-|@dj7|f=G9;Y9QWX!)o;cuv(9t2d&$v%^xM&{V$n6Z1KqjJW0`(#?LC>-sT zM&bUrm;4#~mM*u1#(o20Y>zh-Yh>slZi#jFgT%2QM#ApK>)io1uh(mAx72xSGm+s9 zpoUMd`>vmz+BG)kD7amymWyt5mnx5;#25f&iXQczk!LbcHOO?EnO~sc^rPO5J-hRt zBCo6lF*S;g%h-OX(cNY{o>#DYe9d&`{-wsTWz@>O(9?}o+qJP9%+ZE(+ma3Eb)!QO zn}0ofHo_&^KRta7KfHu!o&wOs5gZCPX{k7Epy+fGTJ)Y#xa2a1ZcX=mRM+T^X0j;EQ=bhgJdN~ov61mqVPM#9 zoHaHbw3Bi}{cEWV^cA@4!FEH4|8{A{V6P7tX(#_(CunLp^QY?N=@WTW z8IFSmhq^UMw*j^v6diqxP9J^PAorIx@f;Q$0xePjVhpnTmwZ~dz*i$qLdtpY1|D*0 zc+OkR^C8On+#{5E79VKs7k4MP zGE#9Jgwkqc!)b0@C$XftAO=@*#kf9kw#9X*YN_y`@-)RhiM7~snFLpJF2k+%#-4Mq zKd7PkpvaD>WnlT)o;Pi}A+wAtm5AQ7**ALAhRdTff~HYemrpq9>DS2YvhbwrCA`Ct zn*vSq;7y~Evzx$8AGi_e_?meQ4;fgX&%H>Y4?*x1Y*3&d%K6H$=4X2j8CFrM@uBr< zUMt5Q?ryWr$SnP0336;RbL`N4l^lo&?US2-ie(0mQ);D`=g?;og=faP;vnS(|7ayB2%t%7&p4l z44QtJx9?4%9atZH9m7+fzECX-O0By(I zB>!5ud1!f7eW~2+%l~PTzdUY^rSgj}f2+ZuFm%Tv@M)v%Uf2j2m zE*Dj@ng@8pk$wuiuGRP#^=6XOle{t}1O=+V765sVy9;UZG)Sx^6e`wf?nGs{vZ%Za z1-^-34ZJCbT>1)l2@c;DsWMMtL5m@fSr-KV|D?Lvhr_w<32`T8t^hG0kSn@~jaXKx z7qL&IN*VOjSM&_=3J<2UDSuV0E;>WxFogn_dzuoT#}Zm$;KDV|grLXiU5H7tF~N*F zU}ozX@UT9~mJ=E{)iSI0{=N-yoOI?M|8gAow1v7C^){n&CEhEHlpqF^Fk- ziNPZ_qe+!`?sR=+xKv&0TdIBnE!riDPU}XePwQ-u-Q)3@(EJ5NR>Pa_K`vd{<8gqs zNT}H7x*P?W-XQq?39@lYtdV}R+?5@|%+o+jWwpGb$_}7OtZZLpSlRqxZcXwUv}k3E z&e%q$&)95`e>OK`Uw+Q=6436)<(5G7OL$Xha@g^uzD4pjsL!=M8X4Pz;NwTg#+p{i zUSn~N&<&A0!yARd#? zzd%!_0#D7nz6HJt)<<&tBg4_~rUY_QRso9pG?Y+yMT?;ppPNIGn?ORLE=<><9Inhj z6m#}gDCQx_J&c%-;Y~5*iYGD?yM(c2%Rz&}BP@Id$x~_p3-Gy?!yvaQNGL2uE%-ng zZc~o*9Y-7ii4OY&{J-SIGAdYSS4QwbeFJW@LJs?+E2JeTCZ$u5I2GQQN)AKlX#6aa z;h;WuFEc&{g4ex4O<(Uc0e$^t1mA@>3duoXXKX;#X?~x=-jApcQ>BK%-4gIc4LgqmmBj%s~rAgq)I+L7uSpX zkZ&Qpv4vc5%i|~y=TnPRo6olIDDx`_zW)enY@2wV`@*x)aAe*K#Mq|gLBcLDMw~^H zcnO=J3@>4weV4EcphX9M(E;Y@^Z}*~@)E{>MXQz>zTWnFq-=ij%F}%Qbsg6?E2P|< zOn!`9U&0%(^suvx;h=E84g+fOxwglm=AA)8p&C>=lv-st-mmLq#{165Z~(k1ft-{L z1PuyzagN83KiaJ-M&(v0_85c3ASDTZ8etDD$=Ft+Ri(4a7d zh3j~qtroBVpZkk)twzuS7NZs{REFdIPG1Y`3ki&O{u{a(?~LI6xB<6XUhzrJL`Llh z97)Tx-<8E}S1n)o+mU^gmshr-*on5X$7KMbH*q_+Far|?* z+0*8s%WDq@DN@B)t!0%sjlo*Ah4frVB9~0F$&ucoJQIzZeVkU#4*L2?W zoX{LaiF0C!;)B!iL60NN!3?I4%P})@I+1GJWbE+^FjbU|1;i#jWYCEOlJ!Z2})$2?#PeYv) z0I%zPU49PC(N0R!aRC7}R}y6gLUgPT>SrJtL2XZcQ1N-bivJXq#Jn+LiQodC;LI`g z5TjJ-*;a%|f|$|$-$JZfs(l@JIn0TNb<7wbw)>l{PdXSKf5jcRO1?T3K(BQ=S=I9aj`qiTM#YWAa;7TV z4zmAZwwKGjMC0BA`Be4Bo5>Rkd!VE$>Bm#2?~uM4UXcqbqxb3c_^FHuSfhj1 z$s+O|*Xsn7)DI-q5(*Uqk5GP7hPw@q@mS~xWE%%>K-QC^^!0;!d~P1nR^kcd`kIlhm?RoX8&)>^{k zaS?dr^ni(9-D-kB^wq8A;Df@}Jh|yXa={-wqo!J)+kvVM1;GvxvT4J8p-e?6KPf|i zMtVLVb{fUc1u;N z3K9y14LA>Y_M%^9=5IiZ$;EroTxyvu=%S?-YT=uOH$TbF-u#?WbY9L#h2VAU2(OTR z@R1$-U*yh+Jp|rVid^xHNl@T^Y@KX{c%M6)GUtQf1_+czRLeM@X)hp)URa90^fc6N z`l4Yj_R0Mc$?@YrQI!~JS{3`gD`e~mTBWro#J~xmuM}dSw zWu{6G`%IgQELx?a?-mWUTe}!O2b}2MHF%tbyaHm{Teo33x8sX$*iv-4&ndAgme74m zBTJ7Q9ODxi>WPV=x!q3UMvaYgL%AmSIevWxGj=}P_#sJ zyRNIaOhTb=^2@lhV^ zQt>~JTb?eA!Nt+>xRh=RR!I)G`nitCwG+JQ6uPfxSaUB}C#{j_a}`LF6F@?t9`=WZ z1u7|UT}q%@y8G(%9x|d%w_yuX>$F%HgF2c0#wuyNHEK|YxF!>$8o0L%nT~BUZXDoI zcnJ7hPiEW|1dqaNS*%e*0wX9eE+tSS-SM2Y%U#CIH-VVmrki=Dqdw``S$>le%_f<) zg-Ro6_my$Y#ZKBL8wnOa> z8{`K0I?!gPDsbG&v4es!oJ=w)Ma)>8;qcdnfrXPO3$eMjZ$(BtNj+*I&HE!9Q zD3<~-!j6$~CU0I_qn!5erU&ZHD|#SH_qlzMCIdl2p)i$I$#Oo&Hw?kC@J5&3zCjnW z`rKTk$@L)kzjsjTs*ycBcUmtn^E)7>E5wiRt&oYA>R&-EL)yRKP5JuW;WCEJGhO%_ zRPr9z?o24}4uXGxLN?66p?swb|I2ZX=c&;_l$s7=OtMdn_GcgGa~bBT(LSb^^f;Zi z@C6De+}(5Qa~l;t5-W@!Nm?PNm_O5c8EIAUrjGh&T4f9eg(0}psZ&``6@%a`C~pmd zLokSF9p6!gb^Hl;;4Zg4rAC67I@%{V<2srrIO94pqt;RFsg+O8aBH1It=Gj`<2x^I z{7AK=y{JDzP<_xyMeE|{02%b3cPUz|59aGcBQ3jE?cGedKnZoZ3&=bE_cUMg?; z3K<7EtNRl%p9$sUP>U67ZVJ*ahc_KpSJuCBWxkIvHaeN72A_KYY4QOG9)AVZ?t8v6 zeD!rPj?8nPBG__jRET@=%XB;+fuf(2*5K^{nmMwkdY{{af`dRpVL4iU4ncm-1&<}- zFxll!rPM4CGknOI#_x#hQH{LjY5e<{@9(h~xm4r7hX`%_2~p!Om9Ks6vdc7Wm;GU% zZPSf&3^@O=RqwCL+vk>InP~Q?$~)vXh6enVJYVc;InZ5EDL=<{G5$dly20KkL01~= za<<%Ua2PxEw-gLQvi(w=v?etyJiU z--(6JpoJWWEqTw}NBC<{{sp3q*emxm-t}(ig}Cwqa;$p3a&`26_<^}wAcGELbsVG_ za+L#Y_+T48*n9IbLhI}P;~1-Cu*K-fX{@AI(@9p-{mfP+PjaQdDVlIccr!?KrEdo* zW257AHnh);M4Frq5(<^+AnB?M2kAmC#?M3WQFv2`doj-RXplYy-VRc8&QA3{S4Y8L zKtf?TTK-+i@RWP5Z@D#b21ZE9a%-Dh`h+YBN6W2k?5f$nD(;?(ms{0xH@ce3$ug8( z@@f^=lcmQ`(W_-q@lm*s8A0FB4;L}tFhl%Bk$n=!R2;h zzKU3^_}qbej^?mzxF~Zkd0zZ#CKgUUj5XU2)a7J(iL$q? zGCWAZB)u%MK>VwqPsQfv#o%bI+8J}8fhk2AZt!V1F43ShnwA*Bq*%pL`N}u&pQH*- zIxL*W38RBX{qoilM=LFrbw;|omgLT_uj@1F_Xbq0kbEzEa$-_$C`WV6<4$$5yr0p1j^-y2F>LOGv%1!?jQ2(Is-#*&5vex|_cA^}=5c|EnH?81Do zCA=wKKOdF0gmON2Fa%`?NGQ}}ENMt!8U-#W5*ULg|E@hN7qqI)<*q~gBk-pD>8o<- zJ!E|Q9Em>n3DTq%Boyi~UA7^CwJw4{8<0fcH=S9W(~BIAoaWNl@hbbbc_)^HiR$|Q z4uTd(I{1e`2CzsZ~ z<;B!aVV`R{2QsZdLZLEhZ&tVzfBU*Zo(EljZmu&D_kcHLkV}_A;W}9l)aS-h=2VbS zsLXVZh6Jvsz@0?`+zDF`-)MBXH<|fk5VMjXha~}y;cmvwV2$kM5eqIxzI8xSVmwOh zj*}yo>q&_{V+nGmptrQ3qda2AGvDM=F+TQpE*hv1wH5y`+)gA zEfr%ySK*rEa*Zy5L~9U(0Xb99diVwz-bwU`?ZSNfmx{5VdvM8dxp9=35=)RX1@+c~ zKJbX$&U}xSim{DOYT+(u5hdDR8r6s#{*CuN#|x-m;RF_cUekJWWI>PoTnGDCIIcS` z=-T$jgLtP}gO^P4-{~u`r_~pq8^T|cc}hKy#T=b3l_RNEzVS#*rNqT9iK{&l^C|Iy zOJZGI(_C&jC05p#0D2yYHkUzSI}p##hcQ)=*pQt;}flVfWX&i#I%4+f+j9 zW+18hbMm>ll^f%IDRF5mL2eEGZ62~T*x!aF{q09jsn4>Qzo$zz{cYoNx1HZn;!l^v zo1QW{%!NdE5QBx*%#_j3Q^p`l46iQ%^gI%?C~;e3>(THUH8jCpLdweiQGa7f zgZ*t^biCsJcCx3OZcrr0_{u5mZ_HTS-+uFGokgvemuh8y`?;;V9iO1Y>R5u@8v0wK zd28rzrzicb|GMr{yF!QT0%B0sQcYht#UnA4660JFn|LHHqr^=viR(QQ3n}q_eF>oF zk@$%ct*C{)IUWAXy{vZEkrw}CIgqOeX?`^x^B(oL^s*(?lYhjNcH_~Y2el;NiL9XvEz7uov5 z8*AK$Mof>aIS72&DUh_*Jg?TUFrPbv(pP}s8@Zrr%?`@In!S|a$;y$wEt$QpDcb7P zBNZO8D8sjF&0=M@CvvG>%-x>M@e?%eT}(ay*zM^YpW8S5GkP>(HZ^y9Hn%m3gq?+! z__dMG<#Gt*EBoWyw$*aA?}?l_yBE>p!W|set#Ad6BMkha5qfZwNTI=#1v`&$G1NQ*a^4~Y<`a9 zwnbupc+)k=r3XRl&)E^F!sjMYW-3T1R7MOM7Px}~52XaEVqpgLo}>Dz-N#23-$jMt+v&6X8dO@wZvv9)uJQw5CQk0?0R*9ReTMaoj!pTlR$x zj$(9tE-Ll8$!dAl*AZqSyBdWnwxc5~_B_6NC&c7&5YsC5w45Db8;``tlvq_yBI*cc zufGra>>?kGv#(beX=uYRGNXZ!$J_rs7%zs7`Y_h`V0;VN)hISi{qZ#BME7O;TZqXY zAO=SJ+yh~J#`B~^`x_v!8%SCrf-(7?)peiY(sm#+j(|5qgIs!OwAbqc)%o0|l(_~3 ze*q0@riV`7y0bsa%zuFxzQ=6Mm$Yvm^LilWcqiODrB}XH-cF3X$K7OyaR;o{O%S~lT7sn-$ zGaDjhco1ThJZCpTZ%6#&@CIbv2rXkcD6FlM?OgI6_bJlkCy-F62JnXRkTQIi`&;Z* z@!JheZq5hm!J87uNm)BkJn4%P3cr8GIh|U3u0KVN1__0_&?flT7iIV^cfN;tmwOyy z=E0j{$QAb%6MGF~%Web>3SXjJ^Dg)IY5@!Ixwj~{1SAv|qZVAE3{SZ``&zF27EE*d z1jhkt^DZ|d%(oi|?!>~jH}Wz5=RsXgPC|BVd9LY|S&U~Q%<`k#HhCt)6dUfApQK@Y zx_3P=N^qQ;bN3GUF4E0MCiD`vJ)`oKzfQ5Y8awd2X!**Yrqq9=;deE->rS+q)1)*j z!cH$%)v~V-m43Gt^=GXWRoL&?M}L~^`h(RK^4t1YCv?aSfrjJZO{4z!4L0w~7!C?& zYg4iWpSuESayJORd=097c7!q&Xpk1|xGnwB1}J7o?gd1@2XBhm>pK?1a8RIpojge1 zMX9*1Bd+1sbD)70XNRyL6@Z<-m zR-~&k9DL<=MKu#K^WaShx}qv$I4IO=2~^;7FCtAo1PO&|w1i8PVF?SnnBlzwF{|Kh z9l%N1@1Q|p2}&ruuft>l@U}e7^e(}_at9OUWqLHR0Dd88QzTG8qk1?$6tJs z-R`hMplGR9G^L*~&OK-kftXZ)n2QHFGo{~!2OF#9314vwii`WNjJRs4^XXg}=`30% z6;!*PcR=L9@TRHB6*o05Ot|hZlFo?txicv< z3j{AgfTHK(G0F?Rc4wEzki{-+*3Gs0f>(LwAK=Shm*j65=dY2|zjW(wdKZl81Y)Xe zms0x1s{X~FSt#{E?N7Z3weO9b2f~}$lS|kBC9OU6`P^j6%m4|6%1muuTkid5o z_%$U^EnR$d+U6du)0NPcLNZ>^Zyp(|$GLzlArZk(06?K!d`goO$okNtePtx5>Q_*%kzU z0)=ck>3*&Zr~TpEm}!4+WH_v7+W?8G$>rb!gboePAy;oK6f+a9t8=7 z#i#`%mEp91u&?R9Ko(5$0L1kf--ZOH zQ{cjsK($=ztJ4d}h&tT>JMD;MjE+dIVX9>3?x?|si2E7d)WE$AVR}3wUqQgg$8_dY1`h4NbiwM~&i27WA$_xSth054XmdX{r&Fc%1MW1r4#$RYfFVZrSa)rO6 zv=#DtGdy>*bM9uuJ_&D3BbPSqE;a2^#QR(=WxfT$M?gR^g+lx8sP@`Ja(^MB?fghP zxwQ5dR6B)zZcoY_01^t7Q9C}@fhD5Ljc4XLAf_$Iab;=W4Lj?u^LZ?WrU_9j_BK6> zwZ|y-VXVb2*6^y1e*1iqn8jKJG;Hcw@T{VS#t%n!kTZSaPxOfz>3F)^{B4-;fLN^L z&nC{Ye>MRHBR%Dgr-F-P1$O%?vD_@QIFy@p!9;dFay|-g+Fln&_SFN%M!P@M=X1-D zCO?3LLS=gSyh|CrdQidji#&qAI)pccxYsXCk6u044!pg5n{6Sg_qkydJOv~amZRl& zREC%DM||`A0%XBF&&#*Hb}`0t?cxO;yOCJ)V#i9Xl-QP|oR zBoyl5P^^=N1a_sszA1rf`N&tNvyc&WIt6yxYZqg*yK^B{C0}AWmAe#i55pU?-D@eP z$Jegu2>9F*X8ar^6zVlKYDl2vV-Q#$BoSCHhxq3E8ku*1drfo%^_&V~#(DISTeAyR zeo7N2Y0c04nh#X1ILNK$PO5noMDK^|eKZ$4-TKko5sl40JiGK#j+-iod<}0v)Fq4^ zH;j$8RjAnK)_WW!Zw(R(m1)0SrVI;NhpUX8kUARP6yjcGFg+SKW5L^TWAb*jZz%wNbSt)5^p zRHwzfq6~{U=Mfas0jWE|n_~3k+qf9U2ZiOjYM~aN8-+BP3=#^}X)#@t;Y+r=dRqTF zN-Y6Nb)x7SDOF9F7$H2k=rysk;7_Gl-43*~lvDz#SL^ehn?KZ%msfTWfP{PNcV zT*0fPH4k@sB7JXo?Tc?C#vr1Lg)$}t1*)i%4as}lWTeSOAhDKEs2D>tl--o!?7#MG zTnMj4@L_mUj$SJbYbLWrs>f4K@G%5sIY=nf!=YazhhFHut~GuNnY)6R`s;2EB2SJ zTK;3oa4fd*+~oFvfUNzDMVt4ZsX=L<$LbRo<;|KDy<)polj$fHFRj|V&6}8ifjP;B*R$dAKi6yH zFCb`hb!f6&wTvlHoB!RSK*`yUJbSmy{UxY$Rd76rp>3xMZ|yWd2sAk6lE!(m&*JKPO{wZQ3UK&z|~Q9rj;* zIz;~m1&eCs=gZxO&45i(S!x(hTetQ68`%-;)|Y=}lD}J=ze;Yu z50b%i`JfZLY2HFh7!x-y^n?qs#SQc9Q1h*8tbhy!L~E4K%OG zF%ZSq%5qOthQlVA5E~X(rB;6OeDC9OO57St#NYdlGJBG=iM|Km>%TyH-q zaHP#}gSC7}{l0E<+-kqk@L04E>sA8A9JWsgegS1K1A&i`U>yXBxW+ItsTChX-4n!04c`P_H~Uk@vVCkS2{6vUgFN zu9p@lQ-NXp1}=Fn*BJt`1Be*{dKqNLtdVy-^ZHSgxIUJ!7o6znq&ywQ1#_P==L%9TxPIbO37x7td+ zo##hcOojiEpS*kgshD^2qh4i=ub)=f6^u3M18ZXRos()CKG>!&vEhSkcxj%?ZcLOm zye!`z%94q(M)T(@Ux@5mo@cY>E1!=drZ@TyPciX5xSx;^1kKRUR@s-TjNgL^e%7?& z9=C0hPa3gMJmWddzmPtrk$EWTxv1RHjm&`+zVd}ZYA%iY;h-%CWef*}YcWyaFTluq z-1@IWeHV~Ws7BR)rVNijnjGS}7+(a5ctl~hk0Z|FqxOYZh*Zn2K70Rs!)xy<`{+Dw5!Bu&+{fCxDo0_i zA#KDjb_p@RG~(_k;#ZsF=5$1^GQ#LLd!@cU$`D0d?fBnPe08L2@mELwwCj`cwom_M z!{cmtb&eY+Xh|CuJHYsr5_Zaog>MeyBRa2wx}1!9GmZN&wg8O(L{rcJ^)LHh$?#z3 z5sjfyzZ6x-LB&$J%-0-0Avx|o_T#|c*mj6EzM`=G=1qANMmwE23ZHuVCbu`N&s91; z_WGe5AC!M<(@*5-@j_o8+xac6EBmkMW9Er*S09^LSRY!dWu*_d8%lH?O09tF6Jd&T z3r}$y{M4bu4cEW|&8d;rc+Sk_UPY=@ftc$vIUMKU-R}pmv5pT5dc^)NbpQ*jnsI=-eJBa zrDEK@x_}!?-ymg^x1$Nsy|Kjf=&hd3z?U5XNxQpr3u;-X`dv0NZUCjnf`r1t(8%}> zID%+o-1jQO<=kSlNbXDo?}s5(-LgD<;_ZD}4J`MX-f!hCKCrGEnng@vg# z*C_*Q?o@`>bOD;V!awlOj_}4B_c0jLBWv~mU-l~-+*tFoTEoJ8ZY-tG2ML9RsWn?E z18aII69icA!_~V4Yvi9AJ><@vFwu+H&|N0A4M#H#L}^>lAax$J}W# zH)wp6Z)(il8*@*_+>mq3FqxivDCTb7A&Pq-=48hx?$DU4h`Fa@uEkDKz71mTteE>p z%q@<&gLjT3ZjQMJVs6u2qSUrCBJRqV`#$D6&x}%s$K2RBbxs`DCyskEj$0mcYtM?b z>=<(+V(yZdTM%<~G51QW`G-v-Ej>C$-1wNgKjuEO91erlT1zKA(Ai#3lSTk&}ZEG00Yl|RQcRgdh%B+`U3WD_$1wpXE+9-&6Hq=rY zqe3dNk*&N2+O-vyyzx$AYRteUEXY(N2-?R1ypYzRJAh$rHf^W6d!o`Ece2<8!DfYk zsI89-o99wcY|%~jXkl7q*A^ocyiUZS7pk*ml7{BkwFOP+jDlLSpsh+0gJ5edq%jNW zqKVp4kle4ek?k6bG%kwWrdt3Dm^X?If^PM420`~!oYB}LE+>+ujoT)T*RwezdM2W* zWDsnZG{+t-*mAv+h#l7=c)epC&5e%jZ4PuaBeH|qt^L{7CJ1(n3t|Umy$z&0rQ)O5 zo#R+qAI0vHiZwcdVAqn^p3S5DyQNZ+_}%Np6N)`jvHP`Ve#ZBSYh#dPd=TuJ{r5w?DN$B|Jxn0ois_~N!T@%zO24Nj32`{L0=DV=$HdthC)WQhj%3LRCPRDZjKKC7mdvXhLlwz<&){%XpiLNocWiM~1k(sp zP%ktxZ5~-1WMxNTO4MP;!02S02ElQOy43I+!$~U$j&EcyE)+bW7veZ6YECnx$3}5P zCJ0X4Ii5Ag86!AJF^vkwx5ahhq&Ob)f{C9H8xdzcInD(Z89~R z0mImN^4Wk~!(7bOvKVl6-Sfa)dO5uA(F}0p2ZkhQ;)MPsF2F-W%~) zTHhD(__vGuWxc3R>Ll?1o{Y>FIH5f#TqXv=L!vXAF4g8sJckfVW_!5Egv78%qQ0rC zUN*y{MQ8-UV^Xj^g)6|v6CFk^r}8I?B8j_E9t2OaeJ#vE@DvNO_X&EXN4*!Yew@C* zKOGqoFU6kW__V_&2%eR;VlMR0N&8^q)?BSVA5AoNHTMEAGNah6?p`!i;WVX~y~I(j zAz;E*UKlH|5ids(tR8c`VmfiG;?-0&Sk)kSEde{ahz7yyqIWB3(Kk{xGa_%MMX2Si z1jgd7l{D4gO@?ULMlioEZS@Z4AJSWY-zn7-Wqen7+ho@H?5Hk=_5;fOGcA{rs#beU)Rm?(OCoV=^3tL#)~035V*4gb zs42=avbELosb*s3m}NN{uwU!AY(D=$BuqqH**Zj~K(M-2Xl8cH2)fTA6JTW!d=9`5 z#{}?2bkVZ5e;MV%APIu6qQ*doHhs<1c))xU$=cL!QKr2mbHM!_N(_SUi)4b}Uq$+Z zU?oDP;eIIUy!#bn@S`b0kxaG0Pg)<2r=M+CBEKp^p>c%5FVZ}qV1S2iY+V$O-;guk zvR8|g(tpDsQ}N$pv(evpCr32?fR!nkAow%R7v1jtr7;X~jt{UA)(g!_@##5o(1)d0 zsmleYW4=v0#FeFEur(5#=7_5=TVJkzo=ks&Qigwmg^SDZaiNmLW%wjmxVQ`-7b;0y zhEIZpi_7qFp_0U9_#{}kxC|c`DoI?1PlAPu%kXiblEh{BBv`n(3?CONNnD0cf`yCA z@NuD%#AWy-Sh%iTy@XzNf5~JDaPWovLs}<44(v%Tu>jMB-M`> zFm&KrUsr~8f~E`W44(`iS0Bj6S8=~My^w?qm*JBjlJ%bi3m2E+<3c5g%kW9CaB&$v zE>x1Z44(uG7nkAVLM4gI@JX<6aTz`?RFb$1p9BjRm*L|=C5g-MNw9En89pvllDG_? z1Pd3J;p0LjiOcXwuyAo1J}y*}xD1~J3m2E+<3c5g%kW9CaB&$vE>x1Z44(uG7nkAV zLM4gI@JX<6aTz`?RFb$1p9BjRm*L|=C5g-MNw9En89pvllDG_?1Pd3J;p0LjiOcXw zuyAo1J}y*}xD1~J3m2E+<3c5g%kW9CaB&$vE>x1Z44(uG7nkAVLM4gI@JX<6aTz`? zRFb&=1fN8U;rmnb&FCqlygo8jZeC5p}PiI8yrX85>qiDEN+A|%|u89r`Y zqSy?d2nqLZhL0PUC^o|>}&4rlnJ@hA;t z_>>}&4rlnJ@hA=bC;0qN>T=nU=}!>I@F~XP|Gaf~*1lQ$y7~a(vU@GtH8OmXG2-Gf zd|ap`aTz`d7A`Ks$AwA~m*JCO;o>rUT&N^*89oUXE-u5zg-Q~a;gewD;xc?(s3dV2 zJ_!~sF2l!#N)nghlVIWEGJIU9Bykx&2^KCc!^ee65|`nVVBz92d|ap`aTz`d7A`Ks z$AwA~m*JCO;o|-`<5OyHW^01Te}YA##c=7VTwapivLw8DNqD1@@TMid?Uus{e{?himr9{58eMT z-=#$V)+OQ6_9?ZmNlE_F@S5-`onK1F$C~Q1CjF)M4=k~_RDWrI*rX)?n#$XvB>!e5 z;iF5!qf5f2?NK`4mCm=N?O%##seEbv(r~H%(*C-p^yf(SkEoJr>)sqW*u-{b#&j#$i=+ z_Ikd@w)gXDKX0$+!`6I;g=c%bVSf*MUbcR8UB+C1 zJ^#bz?UW6lIqSZC9v`>vk6FL(v3}d{+xPA7+471#f1AGA_-gOBJwF?tZ2D%?AN%+J zWUX(j@7w&}9?#xCdw+g!mpLK(zCHg5^YN6;zwP(!{j>MiKA+pI@ooBa$+~ZkXMfK= zuZ1nXZ?A9NlE>`(RqK29dD!pU^6ERS@$KjDw#L8CdVbjbvH6Fs&)D+!!`Aov{kG?8 z&(A)uqt^H~{@e1$@Ai4#*0=K3^Y-`c^R($@Kl;(`Grqn42d(Gr@7emCjqmn+j#%T_ z_+fwF#z$LUwefSi$Fu3p$E^9=^uT_;-|xS(#`|8!ykNg?^NW7>`#o>J-|x4LkNuwS zcYgig#n#_!df)GT8{W41yiIRxc(upx_q#?EGx} zwcoez+xxv_ec$HK!_MCx&;H%-JZyNh>6^Wt6N`6+n(QVJ@$DF`}}uX>#={^ z`2G{t^Y;F%Sog2Be%tgYYu&fU`-pY_&DQUJy=>jLziu3jX|uUq5aX8o>N`(x89`}yn}?EQZ0xA)ur{aI^0_Iho4YwwRuzwP^5 zegB)R`PukB?0p+QK4;k%Pg>uz<#Ahnuz&x6_5R1K-=DL7+w-^K>uS&Mf3fECMw_3l zzYIG+8{W@Z>+N^nrvLWupX)Q8?GOJR>vr+;kmXM4W(_pZ10Z`S(0{rnGG_djF({srrIzxCVpmwwON z`)8kz{d>Fp0q?WcXUm7zTK8@KW79)>ysNFB410dIyz~3k`t14FtoycpW$%Z*U-o!E z+Go6B$G5*{%XjwgKefI;X8pGD%a&*7tmp0Dwmrh$Z~J@wp6@4*+xuIy<~Qtq+T&gA z^Rn^BKCcC9Js+}u|3B7m+y7(#w&i#GeC_kF>C?^D_xinWKi_ZuM=bjNG3$FaJ^V-3 z^Y(okp6%aT9e>#G+48ErzZ<*E1>5j&%)Fg?!1_Jx^Y;9Yx#ocO`P#qFnUAOLw|;-8 zV_vZ3dt3jz$9z0hw0=Kg{kG}f)z){m`h6Q;?cXn0>)ZLcvjaOju(Ja@JFv3@J3Fwm z13NpgvjaOju(Ja@JFv3@J3Fwm13NpgvjaOju(Ja@JFv3@J3Fwm13NpgvjaOju(Ja@ zJFv3@J3Fwm13NpgvjaOju(Ja@JFv3@J3Fwm13NpgvjaOju(Ja@JFv3@J3Fwm13NqL z-^UI-(xQF}zlL%d>Ga>e^)2`_O_@>nfBImz-8xuplxp2_f~Y<0Y~PHT{7QU_bjX6N9e^@H_dyHja( zRx1xTs>_wT&NUmAlhsDK(z@&6Bl=ntJR&2vFIv!{7Z!OkI+%X6Tv_U_m{Za4yj&|bERfN+noH-gOO=wffBJT{ zz5*z=PEXFK)NCwQtq;nb`daN^v3tQYC*$8sxXiBrXDal;O1oVt(<#I~+_|_`@j9(y z0@{Uc#{!K^q|vQcTGbM8y|G?twSiMZJsdYL2C7c8S+fpPt(?$vty!y>$_6#MDbddHKURw^b+ULG)lF*6Qn6O?O0^;Y zqAl0jof@90RMZpII>7-(q0dws%T4-syHl1A(T_^2)okJAwY3xyNa^)@aV;2Ytypcz zFMn?Q>~0LX+G=ii=4B)$7aJG(3H(#jS#PP>#*FZZYcT7|g(~Lll|U)|2iN?C;UOfF zt`}?Fir22xi;Yedo1T`#t( z#ibfHofj%2KU&9Y%~lypy)Ko)uchV%|KEU1EJ@v$Ex+>3hlN0dKA>&{~?s4 zNxK(%)+;uOwTtaaa9LOZCey%B>hf~2RPpoxo;-1&gsCDaT`^4DZkJkB=8t-R)`~5R z>>p;aMi2s|!4v>4bhhgtX8Jb{rCRdZomRE6B2Uzt>k4p+-AFS`as>eIh35>BgyszN#3Z{V^?8262bYw3sN1MEsvR)* z>Z27pMfJ&IZKWx|M_2UcyiNsVxY+Swl0KtnC!ob>DdWh7>piX!+gSL81KU4_Kcsub&jeKi2KT8wc9{#KRCm1TSz8P-5m&`1rY=-Z>Vj@S{1(2mg5Z?pI@O5GXcT}=oPxShMge_i1F!ZS{Pl% zAQ+JT#c-!~MzN(}vN(Km_PD^T9>d)zD{aa`v5Qsp&m&9SYOQluwQ-aLcwUiuhUuyN z8#{TvPIM3(wt_9Z3rAAy)@a+X4?wCqaA!j(1}?}dKN40Y9Q`!+T6}=^tf5Qv3^~pjg+pLv#SQ zyn6|yAfCu{eF6Y*Xm^*Fs~~)!G~bNVr~~+jq6v)*{{(&)%Qc*Ht5qeUg(toRrv}mt zp&lsfb&41sS5c)9Oc)|JfrtEFZ&u6U-;JXG3u6E;OO@4T4I;Db8R|+@ferF*@C70Y zU=Dl(rTH#`o;R8d%Y11+-U1D+JfeRQP&3$LAh4!Zg@~Qksw`Jp&}(Fo7>7Sl3HYo$ z-4-k%2Fl|B;UUylK?FKJFycvEt`{G!c-;meKhYsv#GrL(8T{{?u&FFkL7MTjxWjjD z#vRQN@$VMcT(C)Ci2B4Z;4OqTkd%bd+zJ-nAb#elT|ym)r3#b_9`-hpDIg7EoI^ z-ULmrs`=r$T6-06$P*^y@D~P{BpBr3@NXZcHd@6s;45DTB$8Csl8@r4VoLxT;K;&) zLLjhqpHu*W&eyTb(lVje9ry(yP{=oa;4S)%J0cFWR*0_Czv*lR7x7GGy~4y<9#X8I zpNka=R!Jnl{?~~WrS2q(b}gu;{3rAGZu*&()mg`ZR=>*$-}!7R{kXG_E@#4*|2&nx z0Z%h!Z2znn@xnR0eH*#r19eJShSr1r>o>eZyD z-0)bxe@*&+=NkHiarr;SUw+z+efrXyaQWKEAm9HMT;?q^#{NP7^0ncaU{z1hda^Im z+MdTBnaAbSjK@Bc#$oQKZy6AAH?A^3yeT~9U!>CR9;ZZ4Ul+dq?dePOk*st39t9cp zZRcI|(woCC{T_kQTYFqK#`tO~O$$k9otyX2w_c?M(I30$kF@(q_lR>bGBLb$Nj_~1 z_Ja&%3{GzePwAypnl>t(eHF|6w#aBdhu8MinAnn_~le&XN^zezS>#iGGOh)YPfF-@6zAw!sd}(c9(Ja zZ|O2qS>y7HyVFlxkx3cXU)ikyT>-L7q%U&`zXY21gg^O*!1@n36AI#tTmLoX&(gSl zg%f zlsZdeHb0pGVP$|cF8`)~d0%)ozXqDZD|4S$ON-o=Ng0>liSuECYFzz&qEAeHBbN!R zLX;tLKjs^s1TF6|GrBErT_0Z0E$Pf#FS$qWb~3c_#x2mv=iD#4E6>U982A2Hxwk5} zZU~R~DI9>DefB@g?Hj|lf12j8hd%a>@MXY~HT%eInZ0rO$BCyiQ+#K5uv^nFx+C&! zdX~`Aw0* zAUZuRoc&wE-?%L;6!dXAbfIo{%jCZ`{MgfJ{Vn72Gjy571>-WdIqvd5r^`IEZwrt8 zw=^@RE5_x&^VeZq{%`)%-yR<1CPh`;Wm<^K3>%zzk26O*VLhr~(YShRT8M^|-;=%K zKJ2czH}QX0p3QV#&Ai1aq=lUrFOB_d4s=iK^D z&pLO#T@Zm~FoN#PrR+akaSrYM(SI*ttp8iL@6~k2pLX^uPshFY3V&^azvhhcUrL*12AIxvqa*$4EAV+> z;_l1Nd-r5V)W5UNd-u5lEx|&W%tw~UAN{EN(=s8Zrg-M5^!0SXS>+{nKjz%|c7EVU z_UC`b!HSfKaW@?c9ye*w-h2Ji&eT5lJO<8?!oz=e-6zy8K$X8miEjGUOXe(i zM!{y`C#IWyFq`>}$DH@3odY*QaJ(b!+_BF+=-hEV{^ySI-#0pU;D7JXf4<9I1u3{= zUuM6POJ~OLYUZ0>b>6$z8QJ?HF_(09dDr{1nP2>;AK7(t<~JPYedz=Dv+41cknER% zlBG;YG>=#DM}~|^_mKd6Yxu!ip#-t@%doIv`;~$1-QkDX63b8D7QXz^O!@`zSJBzu z6Tb8B_NLuDPntPs#u3`l!KGafin3r>H-9msr(;}xayJX)PS$-M^J0sbaewgF`q`Tvz z%4fXveRM8tH!v>$Hd#Kto96kx@JN4@PCxnVv+5hShwuFHHBggpjl2Nu^^$0P#yI~% z8xk(L%EV#ZCOaeVJ6ZhR|Ab82cmn47%Q9{-!H-NF6fZ_f(hVz((Xxc$b;^) za?W>#hx=4Ieex-pmti>hJS<6yi!h-{XL%vc#NHnQ%T-3&H{wXiyJA>Feg$?n1(L&F zH+J`r_Cn)jPl<8)5A97iru9{F>GUB|#tVOu1xn08`uQIq#mQ;i6+XqMaaz^Po)@pU z&pli!1dvh$Qh|tZR!{r4UsSgZ;tr4qTnic2 zh#g_v+1WTAkx##N`Pn!|bZh#`7u9ux8N9YzBZ6`H)$6cGn4uK37zBMx^9f@iR|QH9 zzVP?t1LNZ}F8^ByKD@z~v{-WW=XGZoul`LsEmjQolRS^PAA-e?ZLo$H=gzd?5v-1o zV@Ko(!^v>z?dig~`6QqamWDCX zo}BDy`jb>^C{)UpOaio%&Ag5O1}mkXV5jsKtJs$_O(&mr*Sq)%R5h5zuTy%0u{Ut2 zD>h?X9-82dhS&WetZzMrGk`pFnR{yT2k{V-IuTlRg-U3XW`iA%tk&%eY@9__j- z!o9}AAG@3Ztho0>6_)ps*=5hyk``dd0x#_b^?G|mg!p(?Z{mBxGyCv9Ep!pw`68Vg3olI{5K>q@L3v{fALLe=azTDIL7$pvfbag zi`KuJI78MY&dvUZ4E+l#Yt_j^bfxEEe)*0)+3$T8kj%f}@bN8G?`BMEe=G;A*apyo+{^70Z%=PX^p3J=C!ISROB$9#U ziRF^r1-l99U<;ge?%wNOW^>&(P3Mk5r^CJsCuug@2xrFe00LBGN#wGCzaMiJxi9Es zT!!5w^Va9Dblq2eSReOR?;9}wBFR<<_x41J!C2W}5x2w&Vb6Zh-5W=n6a8Zy#bii{zwSr87#|E|4PzVxqCng^qD7&Ru)qtFb0`=xSY_%pVPmx4NvA*K9$Zm;z*tKl!WfrBOEf0@3IhJ< z0LaSWxbJ6xc`*BBIS7Lb{^=&UlrfF}F9myT)CzIMXI@|HPyRRGrenevkOv4iPRfL)fV=$inG@)Kp*!;h)fpMG-|4x?7{JR+G zc8fnFP1+1gSl3dt$+cP1d9G#8!L{x){O`LFLi0HMq5^5g7ytU&wEJ-~A?$vKxc{CebstW*eh~S;Z#=^NsuczcM&UxoQI&sKvpE ztkH~z>HOzO4P_bGxcujInTgW23}VWE*FyeN>bG&@``!Xd_-+DFk;aYU1#k#Sfh=QNOA*@r}4F4hHNZ}2U zQ~n}kQW)0HsrX^z+mH;@M+_$5+EQU zhadqkwq+25UH)b^{e{aA7hn36kk6hs-xEgK4?)nJb&eBVFqq!Igjz`wD|FRQWV_Eg zC-y2$(jdWq<)pu=O)16=%5x#Um32<)w7bZC5zLIszn2M2GsX=vO<}w@A$*Y-=XI~* zk2hbsNy5}Ysi~asL!Mc6h-c@8*y5|%JN;ss+@aElU#8W{?7^UeXoVqc~ zH}u9C7!XiDgR1{qaGDdRHJ#3fcjdQ85V1N+3&8iRA|ELS~%~!ZJo7ab5H@_wkpV+XxD_dAI}N z9S)o{#w>yzHbDPp;i^);dE@$PK(@3G$S8-zE8=&Mq1Q%=jo$=Ij5SHmF2+Qm*#NWsFxlcXd+5?>)!C;N zZ1DK>N9Muo2fAJNyN-4d(G2r8k}96h+$fRCaJ2lay6pZ+=GvDtE%)WjTiwTjYAnAfH zA{m1rek6FsC|B@n+4PURA`>&Ne-YPJB!O}L)41*<-`m4WL9#1ZiNJ^BZR&JC#-_gc z*F>+A*nhbBbO=mjQu5J#;ko|rIy~8#BHXdk=ywy#&(a^)!ij>6`j4lH%-SQwrL2Bk z4E#;ut@skmAJ(x&?#m7upK{CE~JG81njhU)EUv0N+9_($+`hMnpvAw?W8{HKnwQ?_6^FLj@+ z%aVV@24S{DU&FD(uoKguyX8S*Rpf2NUzil(sdDjf=G3lB*~@Ta%1xe%@nMxB^Zq^T zD|8SrwhzYZ=bi383ds3A=e;*X{g*$lbpWTv3xL|_gdxp53Pr(e5*RHh?)A$>3}FzzCR%Kc8>6(T(u z31ZNz;OmkWlFokmF84p^4;XVqECHa9_s1A|=lm`5{WUy)_vRe{_=Y9`K>pW-0vKxH z;3-O*e9d63|GJ+dHQdv8heeG4V|Ut}zj7Js34@#J6PBm1tn8_xUQ1}isHa>K;^0!7CiBc6U;cy8Z=JS7@BBm+n8i!f!7 z=if=Co!f7CMa83%Glv-fOE=lCeEH|xf91YkWllorM?SqouU-8$_nhU?H_9vx=SGkt zXaMrpHlf2fsX_cT1~C3XR(l0($^2{Jt2z*d_fH1dK?bOdrQKg~MT_Y|dp!@(;#?1<%pr}sS(Wnv336|;p@)1PmF|NCWt365cKOe%G%&% zZ)j_~G1HJw`zk@G!7(p^_X-ji04I^F2PAU!rvU1xJHsqg^hvErBKGP-Nc~_&ZLDH| z{a#3R3*ACcZj3j8Tj;xqR$Rx@1NntGqQn@3JV?%+H1wOpfd8x?v6ygqlNzA?;>{d149nh;>{GLIaF=|{y=eu1+~Qto zNCiLkJdygMtciTWcmJ8#6ytAx>LoFW89V$L=#g{IslESz{bwc2xci6kail+tXx&rp z$}hiw8e31icFtY7e3}1=Nu)CuUd3_#&qNq>~bqHoF+( zuz%|<2-_l;p8t|0+RJVJQ+?jlt(~Z(n4(hKN zIJk7Ic5FU5E42l}kIkKXN_lXRr!(gsq@p@bmh_7Z{jrOnN*p(AIK75`r|AzB7@eJe z8uo&{=Q3|`FU^k7&FrgL2~>VHdw1p`&RK((HJiCp{c~A9f9VrhZ;M|>dZvt!X>^dM z^LS?2y_9(uY8tMH7Go%|e?nP4Osx%IM;X>9pS^rV1qT_o{yBxRJazfyIRG|lA&c9FCRzxt`!?swh&gnRBs=xKiY-8@n{%RUo%Wmiy< z0I!^W!rhqtz^o8Bp5}{Luq!J2D4zQaeJ#t7bq#%np_0?G80e7@IseQnYAyUeh%1He zr?W3-f13aPB(}2V%1(5!a$LmHUe1!xEZ=aRS3j1sPy4r@nWa*U1nfWcOlI*TnfFjU ze>(GH|Koo5XEL8n9myP!NphS&P}RLjZ{yRmFU{(Ihc>q>$U|F6kLRAI3T`~+Mu$?0 zR#%>E=*nxfXousE89%WBPvQ!4)5NVLf2rg&+_>g`l(U{wDFX(v`87X2G~u!VjZXj? zk0FjsIEvvShfw-im|x|N@zPg!r=2_BK?})#0(@KPflc^Vv3!c_jNADsI6TjhBxMGgj}7JE-vO-iUHzvs4-F77S_hU3yZ}W{Gy&{GqZFHpUUOB)HDRWNYJsR zu&_AlrM$DnTFP%^bp(xP4j=Xwme47tQbCiNaz!rDFh|h)qutrhkA!dv6`xkN?uNbEEUzSn{Ma6U$AkR64xAW2);|fj0xIo6-}aB?e2H zkoOCVo!p4GSgE1GO|IRU!K!e{*aloFjB~3sEIQ{={}n8tLJfm>zvT!cCpLizSIgWI z$>Y{@xjg3RH{>eNIZr%{<~m-d5W6C2gwt(RWTrTiHXoRRnaBro)b6G%`!rK66>=l> zYQyU^AFedo*bOuhYIUev5}<>}2@YQE3ZJvJ_z{oKKZiXijH8!W=b~)vVrN3yo+ZHW zNDK^52@Hq(xnWd-v@r}{y-=v5(GGQLqaI@DnuR~nNsIyHP5~T(71f4F!wmye0D=rn z0wOs3L);bLS(zb{pmw{9*u2IHf5C6%{(6!urCgMQ;>MtqKd6t=`earI|B;$xbd8TJOx_ zI3N>yg}?akL->3Cj8{uN<{g)#@T%zbmh$F-ZK(xxLR%=U37KAQ~A-*IfAVC zE$tYTu$NM?`V(!@e^c+$h1TXl@4n=#GI&rVFQFMte$4kG8#jx+GD&Ebq{DW*@L zkyW(Rs)N9#Fgv@$R_gwHX70gOok!y))l@V!ebzgE??V2*xkc}u2j=GJwbf?xVVage z%7k>O&5ff2SGe_KE?+E{se2c$t|{cB&7bslz+XX#x-9~471>_v_@vOJbO9|S@?NTe zy5&LAnI-r~YZ6V(uOhT(%p}u*P>ZY*@S0?m;5avieW*1ze6GT96&xp1W6pyGEjKk; zi*VR#gK3g#o2K||%A2iRly+xmf(^7l1Hi>j5iM2=#02JBm1DJHtIqO8I|Vw0j<()wP z!6Lfpseydb-6n#8QyN7>IfZxm()!drXx4TLz&u`UFIFC*8^Xq#EhRL0;5MowpX{FQ zthXOmAs&fnMNci)nh+`)D>07=-wXJ9AAxQ{!Fd8T0reG1>eHyGSZc@|i)|J<&^xlq zQirTx9o~fBK9}0Pq7`{=qy#WQGe0mb2)z&(4h6u9y*SSeTyZBVN#sZ3U=|Qln9k9h zC%jYm{~;M4{TT~rg17`pYx4r?u=0m`UO-x;nN7(tB<|u=AKR!D9~QO{LI}k&rgXE{ z+^BqSom&CsX4V&GtB_o4m13&^L4(u^{iwHu{+E>&1fP=xh>bRWP;nHRk} zEzIkp2jP{vG%BL;dNJ8N@xSWIYNrmt8c6wQrPWjd$+0}7lJW8JR3O_WQM7UHwTagu z$~^SIS$ff%8Ox8LL2J9CFD~4B{FwL9*@qrLgVyC`?s2;cNfi8@*b+foz1U`{XR$qj zwv*r(gs|;;9mCW*MVuBob}KcYx;%ge0PG;R1tn=f4CJ>rNb~Kz$HQrVQx7X%h}D*tYIvnK_h_!*7{FD~%9n7Pb{ZVWYc7NDHCxdCF;jyL_mNbzY!oOZc@{AU zjq#uLGv4BqFlS74^klI!ev%ktX?-3vM^taz7{iSVGv&GJSYfW316PFBg*C9~)6Pwz zB`aFLR$CC@8%^NoGW3cPK!J&kW~q9AO&iJZ`lTX1eT6!RQWIDtPg1XqIZ3dr$wjnv zhb9VXW3=9d;5-ZBT9!`46>4}(%BHN+H?9n*V^6d+n)&iQYn#5FGN47}Yss)^Jz`675b=pK+}etll+ZV4Noi%M#v=mA{22x*MleUpSBrU;@P)PWbW zJ|p7m#ijzz$s*z6A#ZMJq)<4K2jaEREVzZWYk9zuk<;>8yF(;vjGqrO;t(g%4)RxT_eRC6t8_gEU~6 zc*Dy00+~^COKRwatttsGZLsh)^yLPhDPqQi5k0ikF{1H|&8fETxy_RB?MWh@lId#Y=&Z;tR_LR>!4?3vH0hyF`vnoc z`rweB+|^|;AoKEpEvrU~!;y7ln?~HP_3Xf$9Ph3embr=+$C}(~?OdJx6e+_zNyeEP z+l^;o{oQ~bVc32*$l|*J{2V10fUTtd%%dzlA;9G(NvFc#Y_t%wCr+6OF zO=?E7%VWjJoMV_Y`9HjSz2&uL+f&~(xY__l#2jf+tiO82?gdB~J#5fzwJ*jug7pli zd?#tAl{c{9}lRFVAjI{(a{7|k!^8KnY3+w&fH=+s#Tyxhoi zv$0%VndwyOx%_d!bEVigTdZ}-8i~EDHcBm%cwY7A9ddZ-Fwv zrVSpp3_Av!{E}7wWb#Yq3d2Ka+FN~_Mh|$v8>x_O3(^V+e%#t8RSLn9j+~mEL&S@|jnEuLQa#aVlHEb{Q(a0Re7s!N*xlFGw)~Y3SCwapL zwfPK#H)H{V(#t?-qlei?Z%YZ`J2<-FS3LE2b?0wky>m&** zA8Evypru61UGFcshp3n&=lEoxUVOOXX%U<3#z)9Do>HjJrx5bpX)SJy#8m7X`@fl2 zq)7838a8w4Oku%0bt<(C6X6Eyfg~Wu>t$o@jp7>U357jqGYialEBxIg3OrjRcTbJZ zAEYtx<;xe_DL_c4x>l>gW{?}9kt~E8fH6(MbjQ}co=(|WHN%OeV%dX{w+ah}SAu{& zwy_FQv!1#K8lP50Mb8N@EaI(+alMe+LwqlUp2>PojFB|pjkc^%n9}mAP&|^1w4~i! zugs8&IJcA|emntHz1*yO#Zn2B-&Ymsj0%wA$$je8XO!B+zH@jRVeOgp;8T~q??Jr~$IZln4L$VP8b1tb@00{p&# zRri=T1N$z|r-vvy*{ZD705jMF9ze`?0%h8lomXK^?9XPxeXIdPUlG<>ZBZr3fJKv3 zy;3Ld1erBuFSLx3sNqFChQu={S|>1~MZBQiYNduCChZKhvEk1BIhMi$=&d}0$N(I7 zUb&@XI@8c+s(O6i8t0B}q$jfwI6y$i=4;#npV=Mp?p6jDMcfI-ibyNKh0yf(z)N~*g? z0vF8d%}x{7^^!?A8wHpas#Rsn?xhTbus9$b9F)P74UToD8WhtpCKd)Q#)pi91vrfb zPqpWL8c}$B2nic$8vH06Y*bnLgf(M0p1gsv`H?Vd@XDZUU=cHA5WC!@af?iJG$R2U zIqlJN)wRO>>U^CB#&Yt&3tEeaXY-o!g2#b|p9=1r@h~~PX!hL|n9BmdEOr>$%RwpP zlqN8M%X`7^WWf(ctQR}0hYyRp`tV`)`jp{fl)wh|x>U&v zbTmZ>QAN04yTWP)3++>jmChoaZs9xu4p1fP(LqoV_9`UAYPuAWtHfL)0dxtWZ%HCq z^i{S*7&_e9hcp8qtO=C5fDYQBt2o5KU@LJt;D}+W_81XY-{A~-gAqs(hOztLkgSnY zvQS3kNa1|7IzKylym=v22U|}qL;h|vE*CFWTK68$L)B#TO9qI|YjE1*5@i;xN~haG z3?(>w;>pB?A}C8vQtW9WN3*1=Xsl0s7*%-JedCa2A|E0ecUbe5dj1>Tw8sJ_BOx5b zr3%L}5zNLg|MBG(6hcrWgqxO*EEj9-%AGoplw`@HsS`~R#z9^v;CQ`R1DUE-JYrWI z=zvJp3g{TgoL`e85BoxlMJkih1k5iKiB@0YND^8VBd}suqds9EpH^;!^lgb-!LCfN z-&ZWQ?x_@kePE6!;Tc{AbSVO$Pk)dLRNJ3$7L{LD(E(F<%v`6S39EON#;YuMl9!TWAumO1+oTIUPM90WQ zBco~AT1ZCBHcxB=>q78ds*4$u@F1ql9zyyATzn+8g(P&X2u6&BP*wd94{Y4fR*I2Yi3cos|0!gZ*kO;f}l^;KW3%TLY8i|uu2L`#vc;tsUMC=jT8WRzjtEh%zZG{ zojiSl?c%}lSZv_XTDQH*u4&qBgk{(LV`ijiLoHbZp+MF^t6Kutl<-&)@y2v_C>)2l z%Qg)PFRoeP#ob1+bkH34pAY^k@rXJxAX{B;FA=?j~+@aS+p%C8eq4Ie!l&pms)9Uq0Qpqc(+(Qx#D%m zeZ(^F=lvlo&NdNga34U^yIl#`lI1hRi|V~VJ{(R(WHpghSUEf`cj|_ zOp!%4Rum|30`yq>1oX=F5K80>*bb(0$U9!`2sZn+XSV$d?&>7VWHmLx|KST|l zz7R(jI{=*xXoH@jKAisOl8{nLMpS}o|GOAJnJ((j^@j!IBbE_Pj>Cif7goG6uWs2K zV1!WoPvC9yTh=qqoV>AEla>@LNrV#)CL>G;vK7MV&rmqc+BSuo_-3XE2{4^#3X5Nd zK$pIGx@syB7>p1adIEfV&?QPp9S+4Z?+oYuif1q6dqddP8s!5)%2Helky)v7w_d*} zpysnBNx9N_&zoWgJ+vivI=}cqLHlg2xN_c^+_!vYw zWt^7mF?|5q)Gl=FDj>bGxg0)>P-Uh9U)%3v=kB%RXM#*4vQm*HWs%)lWW~qtCZ+Zv zI((yCyeLcwhPd1jlHFmb>ru%d=5(1BCQ-=Sj;791bjKOxJPwBgQA#ca14(F(?-SVu z1unv^Be^PMOn^s^nIqI=4)ujVwAfvmhf|~{(G2|KETHwRtw1hoGTaEcw4Dm@=guoP zYO)jpY81p$E1y&{>GDxzu=!EIL2HRJxvR@6K(5D30#x)R42!=x;@ENdcI=_dRTWA;&!IJZu#ah|ym8@fxXS(28Mhpj=WSD2Ab^RDgj5 z&TV*#=V#9#svOiiWP_Hdn<%s1%*yQ(Nbqj}IaP=YUhsK!phEJVv_mULxGGy&$i9M% zC?uT`?>|P;XA16r7#~t6ryoEt0C}M3ZEY4!G>ed#I)o5_*>bgwcv74PGNn&1GZy#8 zi$P7sVV5Osb9;;)pj z6NyEHEiHFI3=$z=)(k;Cfs|0#@%dmt!T>|0d8|O2M5bJ=1jlb9waA4=;Hf={oCb1Q zBNw?8#RoPJ6{s!;#dQEBh*p78u{n>IsnsuKkQ^i9G(Nfwwy?0PL3QJAJ0wX#tVf*A{@h+5aiz8lxjD- zEyQcE*$5U!`cR1C#erJyq$iO9p~?4zh-A&Uk5!r6Fdk~%NM(`)_-F#{k+ajf-RJyw z`2V`A=fno5Ti?jT_Q>4@(c0To=r0L`U#D+WwIIhFx{A`(nQaIV1ayvcg%t; z6@5hy_YA*kZgBMa874EK@uJ)_j~(IgKZ@()G7tHYkntbnM?&FYZz`7I1qJZKIZ7^E z&iaD*(}LiYYKyCz90v3`4zL*q+3q6XXi|Y90!T`bmZwNaB5@kRv$mg~$8|Gtg}ht~ zv*XiE)HR`h<3FKwMC{{mj@kxtOoM!+@Jox$Anf?X{%NByg|h^19fS+R05Mlw%Fn5Y zmZ;^IOK-Jf%#0K_1f&L7uimB&c z2RoZ#79jO-*r|#=fNcUBC1eJ55v`!$iqZ`=uRC&NzwAu_AIdOCr-A#n8x3L!M~@gH)#YeyM#GPxa&5-3``3_ z`884zLPR98v_ota1WBu-gagXll~53VzS}9RZcm zcn7bz9bv%~s}hO~UVy|)VlF%W$b*U$D!5fS=_U0Ii*n==;xwstiYk{ZRXctFkGBr~ zc0eak5HfD||JpLiQY3E6 z<0w-oG@XetnC-|&f<(i12Xz8jk&lhDtO)usKk~@@NG!1m{ld05Ysf`KY5T3rr_K zFvNg_?U4lEO5ccx%&P^Rc}Mo$Vrdmt7aFJui6zw*d6Fv}saiP^bmZWXFjV)DwlQDw zTZa}vF6>YhKCKA=cWR|$68>jq;0FY6JMH_5>@k6ULlRQn;2ffLp=N~&tcaJ1A{w-} zsIZ3EK*7&J9|t<0WFu{FhNq$`>;Qor0t8^SMTs6ZN6{ES#@uMAYLu!Nm5K|GX5tb_ z$*o-6zRYH_hn4_Jzzp(f5>cVRUd)*cO|TDBiMYQuw>8UL>oQ}acTAu{2JX&zQJ zsb7Jp#MGm>Or@_vA&~|=2S~7~z>TmxqzoM6jH3A*07K=whMWlG1Q zS}FNiRH;aetOgJ}kC!?=cl!9EqFF;>pQ;3qj z-K09zz4dCj()6Hhfv$$KT_pJhftB4lRb|jl59I?n(q3)0I$S-MW}76X%$5p=sFsyZ z$YCa<$qLDyy{Ih3|8YTpfW5zdByoGB3Bp2-(n7pXyN)8+tCWX~@^56@-zc#Q2tkK1 zzn@{tYapfRE$t8Hy|o!#1~iak<*byuI*+6UsaAl1Z7SegtJcA804A+coU4v&#?{&d zZf>zHBXM1bZ5fG^L$_t5kez9Z`-D=V8auW)5=Vt>%j!a=_$|)qd`fI?@O?NBak+ekVpwAk%5 z*>UAp=`7Hkk=m~BkZF|j50Pi0l-j}ti6}`v)1e|Ri~`dTc_V4pX2iv;RE)~cv{5Ob zRO?cwidef!0Arex_ca$p{P6J(Ze{CR@?NfETmD!A?QHW0Mp#tZ+`B)QapmsNYIy@XaOFwXJRlc=fCfIkWwjlL)-b4D=;+A|U| zx5b&Xbb5tvF(n9sSts0p#XHt%)*$&us;x5KY`38i(QNEpm&{3Dm)1r! zwtHIgFHn^1p?n^JHm#DE+ntM|QWJd)7qu9oGFy^HgzYDTUNA1D7qWp6KYApa6;Q z+TCATKYW;qnGlL;pQg?xN7N{_VnK9bBPCHYP$1a{tdu0N(*#~&7Gz?YuZg!t&R4RH zSZgP05<=x<|J4x0E|eneA4I&JF)q=nfNC_o6ZVJGgIVJ@x=yh@jZAznrI8c;jO1>j zrWpNdGl>h8=4OhU$m<5*7l6|MA!X6Jus9;hcxP|rC=OcjJ(0a~5o3MPk5_3`sL}+r zHmG~cC#wx^^Akz}R7f`P3M>j@@KSJ5^2$@pvroYL^q8SSMyehncXY#nv{Nu19g(_S zO8Uvov^90LE4|haFP%_itLB$=g7w-cbxHgNB)2UoBp%|YAzO#@BPdula5tK?F!{upZ-^l& zln^AuXv>b_u&3oJcyPXf?X+rVgD#m@&CJjE_zk?%eg*Q^Aqeei#f*GIA0Hf3eQm*8 zrgT1(Bp92w;R9F)yIv_T3Aw5y5HOd`qjH6q(jM%=vQ-#yH93kHg_e|Qg$yW1blg-Q zhC8H%K-nRD|S(2GXn<%jZ4z2Lm9U>&?A}k2U>9nLT1^TRCJG5SfEQ#K&Tx4^*|WucTnyg8%Dgp}BYY)umAsEin#ww962!8cKmoB|Cv$`-nY^dZvb zAk}0O;fR#Ps&hy~pq&_>o}dcbfdd1Wwju_}!DQ301#Om!(L$mOJoIxEwYPJNkV;W`?COe$gtX;fPXetDSD*cEe>8$e# zTa>JTa_uQLV^#v-8W=<(YEZn{x`)m$Mcb4Gl{^;{5=D+W#bbnZq+KH<7Y(7XwQO=v zwNRcHeMzMCI|7udW%N?w%H$|6Cl(b^T*rx}QgwJ{sGN`j-#1P(6iUR%pAbdFide$& zZC*vC98{^I64%s{l+sl(NHNy-NJsV?K;;q6B`6+P@gS*GbVYVjIH`_ftStkCL7P8S zur3S-JRS@rJ<2BQm^F>>b|tbQn$SjQ1vvpuoD4R)e zVd69)#AzT)BgN>3Oo%!-Hvun9gGGcsz|?G!DP?>f*lI%~!1YD(E9gAEiU23hv_oys z-n?Pcwj9gn){7_%N7GULK)RuDh$Dkq2pJP;aH4VB2wpeRAmXIw-X0+eNL?+$MN(~a zWn+5~B8VweY)>0(3-cR&BCKKQg^+}xcaecYV7Qr?QUj7!X|T(JT@|4;pm&fs_(*%O3y>aGn_UF*YY9ZbI!de_s4YFOiuy36$$<;~)aF14y$N&2X+DP&dw z+~i=&q!;l3ZE`sB3Te+!^xPvdd?IleIQPM*56HwWBw~sKRsu_ij>q@&2`5u0I%I87eHtV?5*1$|ZI-3H7|@lRAs~K1=06EoTT*Eu1XBQI zi^?sMYXDujsiQH;qn$$>4XAUl^>-q^q*4KeizKX_(tFU|KsrF96@9DO=G+^tAQ%KL zknD%!P=2~mY;gm`x$@S_u7qXxDkjAJbD62BU5mh~vE%SQO@)dEW4HSWek9=vJnA)T z2bz&tWr-WXR*0`X46C`RXsafy92S8_iR-3|F%7EX`1Cq?hzUJsZ3FhP_*CMy+--n5dy+uenz+j4~Q2efMrU>^BOrg7+S9#<}PB+_u2p?CLBD4v< z${b2UNq`+zF-@N-1xT53yu{Xn_ytB9DKs&P0#|F*3zgdG7JB0N^7k;)6A?+^!VHl? zE5#aBiy+PXzPUx+(;|`hY)VSCiU$#EmmCQVsu2hu(xPJSTR`oVUKYp;8aX0ql;Qyd zKGeOn<;Fr~1q8a%3Yv~Z#tcQOP)nASVu9Ne0Ucq5+cT_YhuqX;{DagdP_!gA;ZeLh zV_P4ok_wD)qaDugr`{|9)Wkk{nvvNUC25IwL_oz0AI$Fi9(OJt8qPw#AfA zMpGq(cvaDqHq@p-O521ti0UIoLq7=s70isr2{={vr~pbVrmRzRgJeT-0|Y!)OuUIq zW>^VVe~>iGa%COgfzcD&4g02w1LVD@aA>5EK$&W4Lp1keTV6)_?v*?clM^%&r!|}i z7&1Id$7(h@N#~DVvX9@S#>8*M%BFOadr$+(M1s24KwY)2Yw$Zi-hVz6^{2(^dqwFV@BmljU2`!w3<=1n*P zanh8nV}*1sT+0O#PI_z<4tn&^AY&lx-WWmd%v=>k2qj!V)HJXozoTT3k4d=WUoNdz zi9Lto&ytk4Aw^q1V1O-tgxv_6EpsFBCbB$2YlXFW9_7?j5eSXBiA|=aNR=iZElr%P zkdlq0`b!pJ7vyW$ZSZ~S;7~FW!60-Jh2e1=?^Y?#wLdpNc|@li7t8ZUxAfn1q5bY9konc9q{^T&`p)nQ&hJf&BEAha#S;K5h5oxt9`lq1TR;SYF zn=jtO70`#E^c085V+{R=TJw&NlMc&0gNU8PmL7?X@kh**m=y(HRN`fBWTR4i7)Jqz zyG4m~e4IEoC@_!GS2l;H)WJq7v#}!#ssEjb1_TsH)!WoV7`_&ORwAVs7LU2~vQ=sX zE>4!T{c_w2iz4>e)kuaraW>)h(iyH)2pk=nPDhDD#Bh|T?J7Rn$G=8(l(@^!;vq)F zfHBmoGrC)FFpY377-{ja8QMLSq&zcPE?U|U>3)Ye7m@H?5+so#Fw+Q91hiE<_?}V% zc0WeS7P6v!%!x_JzzyZLRSFseat2RP{h8%(G1nq%8l?bZeT` zSt1I3Y{g(f*iMnD{6jNIQu5hx0)^JVadryjqh)tTf+CV!bT@Y>RCHH&+~Zb9@nJ1G z^rVO10KKcJk7Q3WH*lgeSMV-g=vl$L*O&B8L}-+)0YrFMd@Pt9ibl>GGzcks6w@VZ z)+KO}qN?Z+#bBxu^A~lgtRz8h(47fcHb`qAXB-;RQ_KJx75WeoZ7lKyy)Y3KF-nA> z#leyuVK`JCn3I$iPa82I!E0kPD9cKVhSe0Bq!f)GZdAqzfoR)rlFLch0aT)uhLl_( z=og%vI94tr*PX+=?`c6kEX<4IJ4uHH9$CezN%#mEUmwcT+!N7f7;Fh|qoSp#!(WB3 zOq3#2t%1L*2Gdb3g?6KqZdGJ&Fdok3;h!#Cxqm?5>t#BU!gmO7R`BJrZcil6u@rwTsIY1gSP_DyWg9k=yqx zJxn_ft#i*xFE^G;oH3Y}1D{T9|e|pg?JO~}0L{SP0is>6%ZKFp-P~vqP zw<;t$l9_u3{RX*k4X#tLZ?z+Rh?Gv<2Ce1rlvQRIXNJgbh^$abU_dJ^1%%jLL3T){t|9;b2r=Cz$g$$Jkrsp15 zRHX;BxRe{$N7t?t$}5#N_M~2HJ&b^C3PPcY>Zpkbqq5@+Cg5kIenZ>=id?8-9}5xu zsJc7i&EYd#jBsW?u)c%?BURE$qGqCLVq|`sWTat@OpsO|Qf#x5^K<9XtmOPy{?OQ= ziOKvSt3`=fv6F}fhlqwYB}OUetx9NMgXosTt2b?8<2+w(Toja3+u~fANm^4KDAWz; z7>Y}(G^oOw1gC@EpbhhCrG^eE+SXw8g*bdT&c_pq--uP>O*N?iBF4&#qTO*27IxY( zl_o3-@H=NVwJ4J~qMKT%vgs6WLobB3If5raEf#IKW&ASQa2XN*Q3s=etrUkfaRK$E zfb|PtLp&MYkhEHz1c7i&uU$mL3ohjt*kw{n+`EOB?>j{6>?DI!i*op75J=Q^ zloBEdK4Rt0^5=2YvXK2=7qFe7v)3|0V`=8Wa&`7cRVwz=UTZD7-c?QeVAq|YZ9B#h z4P5!nLR&*8CleK*8C=RJ_Ym)R9#GI?AV|WtxKP_%p5r{gc~)VBWRYWODOyM`H{K@G zC+uy|MF`S(Wz7f%HafR$ zt22?h_C#?Faf#&u;u^%{ztk)vy4}yC=y+7uRj2==h>8T@2>H^HYlE4zd`W}M%*Bh9 z*22AHXZFsXx|fGj7&;-fEJdyYgFfBu_*hEM`8JuszRLAWM5s!_G=o>5vtqP<2|haz zzak0&byFLU`k0z56!0q)^$hhIFM$ZNA?}#y@I4(YJ|~5SttgmLwT$<(&ol#DxCE;q zBzHxpwc>pVn@|PZ#)z*drKqo^&BqiP7wH$JVuMAUkS^`bPsiiDAZrpASDUd&DI{E^aEO&nCYT9DG!Gn88E^)AsO^ z0a(Z#8n7bvjKWFY0?hcuj)o*N{@YrAYb#!jFaZw7B=dj@&erk1hHz_fyU^^|rfl0g zN&JP059rqD4WI$`+AKC+bm{4lP6iKSEfFaxo|}j4Pt}&v03>Ggwua&0Bw11Mr%r%=e2CEi8RMAUs)^+q7HQpn%eninUtQqTb? zvlxXjHYHLcXQfUR{d0&tApD?K$J!7iT0_YDDRu4c+^-+l54wyV-`cjYbun*rgxf50 zm>xCeY#?WhcnH43c{YWGatUT4?obRlnlr#tk4^JZ$g0jk2&=SX2oeBHpcRW`J0_bf z^p3{q*sUs)IQAV!6^?j!NDzsYK&SI@N8_O{(?u+^+Ce}Vl)ZTb>!SJvNP1Y$FQh`; zLc6B4_(=jG^h=J)J_^y4T0K=#)HMK|tIN_O63u);$0fW3CX6b=OCp|OWkgm6=7@Cz z>>MRUCB#JFAwJt~fEVM8@$JsQwG}0D&mx2aC`_6`fDNQhOrP=AJ;*!cbS4Wx2*+%Q zh;N6=h`QS8pz9`FDAX^@HrR_*mC>ZP-9G%FZ@v#qBN|do+>fh~5(i=MWb4qQLBp)U zjjgsxAw!LxjlE0Be(Z3%OENz85Emk>#f;Lkiw?n)MS>&577z^XfCl>MTOUYk4;4?3 z*sbz?TM!BlIe}=TR`a69!hw~*7#&ceEvBX^`s=j9+i9{LfE9$&Zvmo{rWXSY6dkBwlS-dPuUcl^_!K%b28u!7evDDKtjLU9v8I6F7K%JQ5os5K#qF)>0!jTKm%1K z;8e&=cY2v^>ZqR7MO-k|E0%g0T1U){+*hn4D}H6}fio<4QXB>Cq0njS9wP>vzI1wa zAVPgI7%+}dqq14J5WH7LrUiJn3M)|Jq6na%gqZfG3g(F1m<%KuLQOd<7n3^|8!}-q zJ@JigMuv+YTZ?d(EM;P4K1D=PA}A9Et#?4}v;~51N_5(Xd$Qbk`vJi3SH91AQVe8b^~^n=$|~V!F(> zHLuvc(A(UCpgZELzQG|9DqSpubN*{WP6|#@ekOPt!J`J1X-Admh4OAQ%>)LN{n$y5_oO=-mg6ksljx~N2X(XENWsrWJ`VVMM8S- zHN7K+OARX_dWKWDL}S@Q_~1;bTqrE5WWj}51e>K`PoW1^Af*&V!{}imHYP2eEP@)- z!+`w-AYi^u1&$0h?m`+0E~Vbzcz!%#|Bt zNgHN`Fv){c+M0)UOi&olcw`imh#4l#QicVwYiu2@QRwX0J=IFBjE5J!^Gx9sKyD@K zJ%X|mup?9fb0~BzQBmMnMtz`USlWDe7*)&B5-yAh(aoo07R2yoz_jTAk?GF3jQ;lBT)y)fj;NtI;8YF z7L$~NXOvn{1Lns`x1+9PVzC1OhAta!xXnzaL8&(qR+BQrKOrb-DIXG4X ze-l5ydCQBDG3c|wkb{4xsB*Owz^_R7ZMY@Zh#G?f0UnX1j;LyM)Q?w?(!+wjgGpe{ZX@Z-bk8XsBy5GIKux(@EvA|it8NRw4 z4(!AtLMdJ}UaqW3U9z6ELQ~!dgNbAShf)ogfS3XMQtL^_@lqtgRZ}YYQ$Z`1E!)?& z&rYXB5bjToxahDY1U1Z*86?Sqgg|>PF$5y4^nE4BM1fn^;f(J0mUlxm@nqsXY*dg% zoTKKs{*Xr+5&8DC;>cwhs0ag9d`4+Z0GrxcKZGk(GSZ z`#NAEa%?yh5S-f9juvL2Hd1bbuN@J(q#lF%q|G*D(Sbb5;7IzjvkkwmSe6nadXqs)0 z-VZuKHr81esA4KMH%^O#nIQFu?wz~XhW$mAH}pkbvit-?Sv(CAf#IJTi;rFJt4!j( z6wJBEEkuF_$#2Z(h!eo5rAqX|^;hL=NZHn{8@zmr83~FEdo9W_pgg*I8LXBVM7s-f z5XA(^M~9d9d&8w=(j7Ph52clh7lP8tb(VFhAYtkpG5|?3NI?Q_BYa888Hy5vDF#7H z(|OY0bS>(H10Pb2AEXosNFg6DfG0LLE4ILj?qO>a_Cd_>1b(3eGZ>vbsg#5K9*|*C zBh0LZL58K)M^@nz>^N&#T#V0KC(7O%pN8f}5~_=>i}TM1JDYHtiPF+0)$s{z0p(Dz zMyFuR=7&k8l8~x{*vC-qB!WiK9n?q>D_VXeq>X~FN%VF;Pqn}rO|*k6v8szm6H;$E z=%XhIPFA8L<_IhFX`seO1@dactCQTt)hBZZP@jUTw?H)*u@7W}k$=+@vK`vJ5}TY_ zo2xYr<@2MXllhU+iK+3i$;t7lk*UI5EqZmbP!Q)k^-k?=#M^Fo8O9?96TKEE5D$FJ zdx+e7ffp#^5wX*4BSwWD_G62!A+aFvgv`&1y&{p5Z}%omp>QkPZGcu33WhK+l;ox^ z&VX;p0>~Yqu1yF9rhsK>6})A^`8G6r;v((SMt#2?mL@AQUt#a&{E~Jsp;+)i?KR8Q zg-?m`QQ#;xXQPAy7LB&{67}#ajger7wklExj%n{y(duARwp+P-)H7 zkzAr2$#FO`2!qIRV{X)v=z>K0#4Y%Gd|X_puC_OGT5?t?6Ah#ml?piJ5rUDOGk{0~ zNJof06hS3{{`WY{J`_&}@mi`~ghb~C@6ALVVT5y#vB-A}`yOgo#d;@rSXeutFlu`m zNZdr&x^&)DoF}Yr5HXG_FLtE3AL_5OU`%-;kf4X<_+e@gTh51hh?;jq(?veWY_ zH1#z~%Wi3Uio~~l;Pcroh3n{~>awV)6w{9Yc63HUfEXw>B8D03dJrJ^PpGyksCBE0 zeMLBkmoL;eKonpqL1K2Nih|;Z{i5^%q-1QsAQy@P<^wBHB%|MsRjgB6Ci+VEzY1sb zMz(UPRlg49Ti?jL@O55S`i;G{Dj=u_N$>+|B`$s8^an$f+@v}|Ga!gQpwJ)#$7f)@ zIzE$6%^+ly!lKSlS^N8n#nv=D6~%I8p1P5=E1)?L9eUZJh72|iR6Z&|8{~e~kx83E z!!s}FdPhNe8>JL(2dmMKzTv)DMeZovg8_|GLTJ zIa;zx5Kvu}LAQMY^(u&3syv(TDS?!`QqhhQQ3*I;E=YZ1(1{TX#}HuCA=wjbhL59- zOf~QrbluaVTk&+};?z@2fZYZ+{Qsp_&-R z3N|dH3|saZ4ZdMj>=d9Ns*1&%*p-co#BIc{=>!wh52_%@`y{j((9s7UI;S)25>IJU zN@l<$RgRz_E=tN=D8a1_B*qBfgd5dT&>hD<)Vk7|^MxW>Mnz?R6O-p!eK}+g>V(X7!&_TvcvZBPpFCx(IucRvU4S zqrC|*HE23U-)tjeoCZmzqG8u<(x)Q6A0Hi=yQp|GvRTYc~`Vn_hg}J|$X;V=T_ctsDt#M_)Ya-SfcQT(I*&&^Il` ziuzt?qM!vc_MU~QBx`U(=Lsh$1jDiWfWhK?anj@Ln=X`8AsuZM*E?xa-nhWicrHo8 z0tBx@pIlV|9bHgvBra(XLPxofn>20_!~#ysh%*LLQAON}EhJRZq981>d!L*76vVwx zO>fzmZBb|yC^&FvbxgLuGznN?ZOB6hKV%%7D0YgcA>%=F09?ywPpl? zv@4Z|Reed6yWmfv>jJ9gkO=R$Um%uBpHIS1gA}06uP)L?_Q1e?E)Id9LDFcT_+jvY zC|*vU<0kEc^Qr1dxoxs!NB6x~ASjWsQYza&My+#={lzkFQc!9_>if*y{`H zVUc*iz~~;n>rkZQ;uJt#JX%q+3%gL0Z7&JN7qPx115`XoiWA(Eq`^=T3oz>TMU)>h z>xU^)YJpt9Um&^yhI=PS5hs!6E(UQ6x9s6;G_DI|7Kt~wko63zs0MwugZs3S#}k@!kVD{-UHDH0))ASE=t zn_nn|%9rOR#ZwhbtI$c7qqMIc<5`JnrTa+z59@ND0E0O z6BQs~2#z62GFU`$m{prdU>8NM*jItM4_OMc;mKd>HY$)V)z9?rwu1eZhS602ae)b*ap zm6DSZ=+$s4XpRD0!|9fB$~8hx7pKu}7XGE_b=2)SPW5q2!ldCOA~Qr%bcp{`qQs%K zE~-g#;0jg++X8eeRjF6!XsdK!Hm5~QQ%4cYMoNL?1(M~0W+dg_CSd+Gi@k9TqaNx< zs3=fRj203Y1+PsSHGJ{4M{*aLHv0JUSS_`jeOJM&XN2MeMn20sp^FyboJmAyz6V=U zwFQJm9NrQ|z`*N9R$A&$h+LLVC~5{CFiizInpTN*8$Gki7aLv!eMG5b3!?aSM$NWh z0=a@X3qZsLyAA<`U2{)G#0xH?8ktvuZ{92AQ@JtL5`*&IfFIa$xQLlyoqtFy=}Dr^ zka!#NSBuXG9H9pgVfun))9ce@f4K)0^8#|&GwgVEZWTRoR`cUlGaPdHGt$B-(2cMM5}Nd zg(6$5z^N%uNR#9l>a;yq9Sdov9&IK8M>I0mlzOx;Hq>bws@y!#9`*>%6Xzalf>t!3 zCD#uSUu&f3+c>FvaP%fXn9_O*Aa5DA5;>Ml%9C|hxcdtQk*1-%`eL!#I)f?=uvERb zUkikwL@) z%Iag3N;Dr?;r3uk^nxM<(V*_crjxcz7hkhkn{gn?Jw_R5I^>>;4W^ExeM6;nl2S;~ zn_Pm|xcYmsPI3MUW3;McNf4@BgK7*DFAXX>7(2-+x0%t92t({rLB%fnWxZ?H9+kU@1w+o;%H#Ymnws3saV zCD^pTzHhQHDLppu5wkQ+Rg(qi z{E3)$tYmqJ>lHxpS)i|>jv2Ke#VL{j2bD+4WfVkhHYOD$L-My-4NM`*jZJRSgmvj6#Y(}{*qg2=?t!gbQwwa+eLzRCR04Z|nFJ|! zOR5eQSpsQyx3ak$3C)3HUXj~9>b4ny$zK6%GGpUVgOI@==4Cc4acm(^u!sDwl)12z zB`&R!y8Izvo_3;d734Un269cS+khRs%!fk|8CyRhPE;&NnMW-*4{N#LEmq-|oDR*! zMEy~Mf{G}V08zv?#26_9$%i1-kSL)TiJ7WSvWh_$PwMUNBckPy!`cnvQfC%sVV(WNsSx-?3CC?$*q%zr&q zEJO88eem?ciN%?71=M@5fUv_nL(8!poOy&`DgWk$PCaTEdUvS@>}izAHD)$ z4)&H3`A~E@h<{|0Bjy^z75eKJy@NQz+Bwr@ay(G;YMKrqPqp0%mBS~kgb;@-e}joO z+UR>nR;V$lQK%u8pMuyD3eB@dOLHu-t-S4|N*I?wLUm6V1sI$W(vpY2%rOF zQed99gi;L(#kG~x4=>;lMq*HutlOz}L<(N6UPw*fbFa5}W?=>`s2RD4fshiegINK4 zRK<^jLAZ+{cl`nFU$02sA;s!N-~b_e+8(JmMnu##V4lL6qlpddktZ~om~R3Os1kKJ zk##22H8iDsdMr5fl8m(=J%d0@0<5IzMH)u=1RL}5i4wZ zDiBdsjFxZ1$Nq&q2MWDaw8>ziXD&wS!2lP4OEHEEjhy18yb5su+oy%vs{hx~)U_Q^ zqoW44tupw5QsDH*B8V5!G0jvt1g`ro3mrHdN)M!}d46YHP@hhj`B@IyR5);-H z@zbB@L+OAhMPeaTH`D+ICy|?^*GbvK_!AfuaDPg|e5gFp0x|+BR<~f9#PzPqN+l+W zZnX1jl8qgL zCy@GN$385+qdxg*Ff3ak1AxIk>s?7dt3>+Pocq0TApu1Zz|wp|wBah3R236DXJ_#7 z1OFIe&hEWZhR#&97~e)a7y?J8kRnd&BS(2IAEHZt%j0uw)NLZ(#cwwuU4Hhatz8Uj z;W>RW`qk|1+I(-&^AK)fjQo7H_;(FQ5UUSMjw|^4pI1AuV3Jm}5mD4zf?)TU#DHTKbtH*dSiKzZjFja`g!sr%&v zQ7N6-E2(z7qp{)}uz;b}K@pYA);=;Gf8`^Q%ALQkKzXMOOFU4;SEnjjY)(X6Dqv`&Ebn{bLTC z>rO^^Ij8iKHak3Yt$E-ALV^!`ox^igW6}7f(9B*nlO13dZCKr-yc6}&GyTd0{4gb? zZ4P_Zx`5oFN{(!8)x2QQLzh%yj7$_CG5$vQIJ3 z)U9J^UE5Q#Gr@XE(FZms)%{_y^mILjaKq4T7aD~4G@AKf++e0514q#PrwvQV1*F!p zhC=5{a98x-;K=T!Rlps*E!j>DyZ!%P*Hh|=(AG*gEt?1ZNJI&4=K){V7%y0Y$t`cL))1<#)rx5KF-1HX2 zV`dM%0XYS9;k;c&2l7t3g%?4B6)svOW!Tf zeFr0AT37M#iSK0xCa(1Xc;)q6AzWh0Kd7La5I|1h39lTgd`%^7`27B80)0L&S}b`i zt-f2TN;$Jnb&)XQM!Wz0B=}qZq3AO#@{ zd*i1l(+W4r;wC9>cw^vnMr-Uq2oz+czgFSkzb%v^_byDDj5oi|e=&+?=R3R@i*Ln$ z9rT5^jSK8HTzaf!Vtq7nS~fpt?-Nj(b+cV0Xk+LIsh{s&#E@s!6heOyP5EO!hL)C3 ze)-|_#GN{;SNJkj5EIE_^I7Bh#2mXZzp~e=SZaJ3hBRTi>7<8hM1NnpB*Ky~J+zne z!HD$4YsS{zVOfxVS_sa{Y2c!`&4{Cc+HnB&LD@bEsy5@G32`#t{MfNl9vFyyD6*iv zarLWBrV0iobS%ad)9@zM+H|%QT{lBmsx~aiUW5B{u;&O5UY?BbyX$k>sE8Q~qIF}9 z;6htgm8Zlic?0|JF9Aa!^O~Takb|nF$yR%aOQ+d3v2tj#_)96946)duYjb8Ts|*lD z@wC#>N-Qz0CS>o?rcjOGWs2hqJebQixER?leHtv82m#|}K|IdbZhRC8+w^NIcg~BR z2Zxf&@M=pAGMQ4iA-L&?rz}=7aEb`Yu>U8f#v#xHmUJZo4D8v(GMM#v;%!DGf|Ea7 zOd&>roE*cLaomZjRu*^-7|Ab${5E4=PAtZ!Q_Fomckr4!?9zOkd4V;PlO+AMzB+7O z<%^lRxEu2vHs2T$9P((DU>s7e-EUAB+a3{t3lf68F(`D6fL-@WU%VzR_*6h13W0$M zS$m&kCMrFdPv|gW$MK|9k%U+Sv|IlgTK|+LX_nkohJjb_Zv}K(|2yNRgse5QA}o&e z8Z-gtb3|Dj1TYtuiJk-}jZFbCsB{4H^4sC)=2mz^&om-#jv-vi98+G9&q+Nt;)i1M z9yo>4-@+O?+4?hC-$w*htByR7W0rJM{WNn`Ujtle(n) zJGZI&gF4aK{f$YC1ygT-A^ISsk|H{4E$8@JML$-(8#j|)Q~DHQS3{f2<1B{4=GXC8 zVX6^`3)2ny12O<%pbEUs#_pmn4u_Fm_UdGM7|ht$#l0;JI0<-$C9R`l)jERr^v-iz z^z?G{vcxl|1lSBj$I}AWIw^2%Y+?L( zcnO&?$hM%6doWsFV040@=t46tX}D z?}-3Fx!{GPJt?N|N7E1V!B0ssG{ zCR;cFT|JsPPt@KK`7#Ap)$d>d_3^AQRXfCWb+&?<(&}J;f48Kkw3^Hz4F_anx$L!c zUR3KR4N3lpy5eN`iB6~MEg*7)rnWGhF6U^ry?>?dn6kfQGVdTOFckG}>`C_H*`+X{ zSEz@KAOSX9_7@|Ox@al*?^MFBhS$(-!Z;1-h{WN{mMH4@(F767df6PHIg&XSuD*b- zA{cH2MW7f=mW6&JAJ_#9p+RaAx)xkSYl)n?tk)%~=BrougE^`g*CSMg@GD~}lQdtm z&HRI}RwJyH;@O23&sg@toG|SNoeWpEGuZ?8;cbxQZ$Ob9E=(1&)KMjmi1+tAcu{TV zCf0TX1W084LuRF(>oGI{-TA2J(>yy_vQ7mI6hd@CF*39!dAiHfP#=|iLSSJvmA9Al z{~RgnDzU)sK#)H5n%0SjTL(E1IxLmwmaODq@$-?EB>35Qwd3X9%hBn9MyJ`}bp7ot z=VG}2CBg#>WKx8AOlp$9ijmrk<0r+RX^vEh{1UW0L*W+R7US_UVj2qydtx!KM~gMH z?qdcM%&^K5IYY2V0WnveW2iR=42|duL%KB6qWiCW9Aa`WLJWP%ZoG*#$N>gz;Jv%_ zMsUX%Or^H-U3(`Sr~W<8E<%2wj z^zXntx-3+819FAU%YeR$zEq?&i;dA+|P7aP3vkj5PBb4HzRz(qUm62bH%T6 zELpN4!Oi?HY^eF@LD`*eTRN*2H3HFGb2?Hjw zX$^zcm)-q>a|I=;w%eTg_L@mzwPZa9u0`KlPCT!Yo+lu+S6-f!FD9$%n>sX0^$|Q? z@^CskUMw*12`D*o*J=Nrvz(M{z+Y}06J%Q$3K6N)3A%xW3nIZFzTqvnKnY)E+k}jE z>~V!wj91Vb7&>aO2x%)ebXIr*Iq6TL4;;}LaWaqd+9(*`V>+V1d%C*j39}(YwkqdK zCQwscjvxdDc9lS~+GEw;y98Z15W~FC0qeY%tLd;#E*x=dA5sI@oraThBcycqbsjPgsap_L=abn4TM7X z2z)m2P1Z8CZuh6r?`m+Pz;$cq$eK<8!n_?T`gK_YDFZX6UI(g}kxT-8%VMP&cMsVs?k*h;*7+x2|FlE{9H z=>|jPNJ6TIiRUYUIOMcK%>9}r9=s^L#GbUTz;i}TMUM9Bxpo#v5s0&OLkv8I`mR$c zfHZtzNmx?VZ%zS8nCc)JFU>Owk>@7Vj^@Z2#x(G2J*ZU%f%JWrv%3YRMY`sUxY41` zRKK$dOvooQog(IC-6loEP+>h0FvA#BM4jn5%ZJqxgc^;|s4VTh6z@L$(#6MqhAmnS z$Jb&AIDfYSkJ-+)YfA^OUU4X~;9{au@uqun`u_Ngr^xzS6uHqan0>KB^R(%JXr1=s zCgh~%&4*k5NaUAMaUd=F(jcl<%RuM&YR$jf<2d{?TSb$qGV91SC1w6`wVo`08mIvt zP?0VS?qxplUpGaHSpvu>9ZMe*5=4bazXP#H%-)$y$lfv3?He719F?NdCzE?*%t^p_ zXt@Bv##<0kv8~x4-QplDzVnuq->u_H%7q3Lha{}?)7hmP(#kGd^zUHrA-6D^e!TjF z+Q<3^X5q{vx}tPISXF1A#vuP!Oy~c_R7HJR^!jx;TW1q zW+USY*LN>alMcL> zZpIOjb*^=h08D~+T(T~K1hzYHh{R*RF71yp>VpT*X`XONbVa@rBd!NVoHj2A@8wGY zttRHz>@LUuxzpx6woAP7u38i+wGN@h?W`5dUePk#R>70%Vf-ZitSkH>hkz(+h>ldc zH7{uL`^n9k)9%r+Z;S)z8x!@@*`xt*sV=^0C^ z_nlC^=dUOn`%=2h2;s8-8Rq=hWF;BCBBqVq08~bZH_K#d?T2Hd0Eq-H-J^-uOLB@} z4_Bb>(Don@LaB5ru+ZrGHOI?*N1|>s>t)j=irq0td;Vh9kmRzw_EMGK>p(UcS%5*b zMWEi}E1ijQHX8i^UZCI6c5|Mu)TL0HkTgAoo9_pzl(rSo2Gnah`ueYwZct3PLcL7m zP#>8{qtw@G=g|VP>TPI%m(~zmVFA_+@)^c6tO@*#GU)!wUu63gJFeN4h(NZwE(whlLx&blKBE+x*CmvozknW0-`B5KE=EO6tU?Yts(G~054f^RR-M& zV#!P!y#lOKr|w`t+6S)7#4IA)V zOthJOttUG1(r6$t?9Cj5xL~5lq*A3=12h*Cj^i5ssB~Ojy|R&EI`zi){BzCq)K_Sj z`-8j5%-2zzboWd`T0DyUx8-V=ip2c5#;JPI z{Xqb#BHG$4qEGyFLP_>kj4(mb_^T?XEV8Tr0uvfUSbgA+&Qo-tVt^vv2!_TVvVaNg zP$QbVVPb*OmZy5Y$G)(EF@p)o+TC3EMTliEwbnsnb#yT!Ny47m7TJnCUZSpLX>xYh)DrJsyg&J+SiUkSjMFbyQIu(1JI!MV;a8!&&C!@YT0(N#FsjW)}llC4&8*#Y))$spK zKwtPMrW23qrPtJ$5Ex2Hn)70Pr4-SSNz%YPhR3f2Yp zQaWUeJ0Eq)bd}h3DKeW5ux8x)%kLk4t@-W{dY3{)d`Z$6S|58L;q;XxP>lY5Cm6Kr z6DoQ1@KuNm0Sl^ohQiO1xU-?pqXMv0AHH? zw^&IBtL_P+f8T=S)Phs8m|I zM8_;5?ZcP?#vwIDnuvQ>K+}30Ck|#Vao8njmC_%hBSLK?F)<@dUu2vr8M@LtzHfyd z=Z&5X+3k_VDcZ#;_j!pKKs=6W+qp|s6f1fy7HQ<1E&m+N5erb#gM5)z5N44xEavg( zc#6Fx^bCCD;+?+UADH7tE|61Rm#>S@-h^w=iKiHeAr;;5ckpQF@m#EC5B)lg zsb`0p3a{t0)3t-SszneeO$d;#`jHJ7pKPnj70Z+R3QIL{17U|Z%Nf=m8wP5!sc=Lg zs#yvgJC?(a`aSew5cfn?7`+aV(sk;H+UuYm$WnW_)Fht|FM-Vg-cVOk(&JXut?TUI zP%>raQS|7w3wY!(gR6f2PCA_$*~2l%786sM7}$gz!SMZO8{+mfHjK39U)_!WEUqcB zs96adgcX*zS8y^CkkY$wEtWlwFmqkr(m>1WnsvAv9;hS+Vz}YYX_Se=VN!{$1Fv}; zV)$=F;czg?t5=}kxw6J%NZjK;vE;R(4-P^$e$?3K0 zEro114YkALM@ZrdRP(ua0`VVRx`~MR#b;a3#uJf?aGpGhn!?*|_yk(C8sT0dd2c|U zmPw;EPq|K*&h~US)=JK#j7lt5ewLEqWN*dV`&m<^5!4=Pho@|Ny+r$PA9kw`H+wT% zj38QRScj@-yEt5g>=Zy&)g@`j-q;8&<4Cs3^m3W*+BPlyI5BE^4cZ4~aU2ay;z%K| zMRL$jXf1;!$%X7zHpCZO=v^w!VHQ|X9RmXwbAR#f6Il2lJ^>{{Wy_YcQW(*KNcy&V z`ckB~-}N{tLMEi|Y%n7=_ZO%DwhsVYm8D-avfmEF(DY-RV$gOzv{Dh?&c`a9u-W)O z+l;~69iMzU{ng!N7kKz%QrhN<{mRED0@5_s9GHBn09DqAJS}Zzq~j*NYSG%eoZw+O zBv7YJ`4LUlQfhhsTA85e)Z>EbJbJU58F7>ELGi^Ugi4`g2O4}mN^k*GKnNCI4n=sW zA8vWQO6^y`WHB6J4nD+6n(DMZeuz`8IPq{WAALrtzk99}CGY}vit|5!q!Kel0?!JY zyk|qTB$D;el8;)Z(8F}W(VG~%49g@Uhy1|CxD;tOP*}g4q$gn1&?RS)$nUai4tkB< z&-2AD%D7-#u)2!Td1Q1Ji`5*(l7-e&bJiA$aiUqO7TlkzG>}>Q@>D8N87|u*8ef#% z`KJV-n9T>|IyVQoHJ{B9dqcxr_R>QgrpaoW%_Uco^$@kCbAGh0_H)Y6N2F_zgWUx? z7RMxl4eHPvax49n#gF4;cpV8ZB#zICK4ve?bf^XHGCSmS6pIp87A%U@FLQ_EDK*HN z2+3>|N+w=5-J?8Q3AHrl?#p&O5hb`>Qp4BsP`Sc{bJYB;^$CzUXXlwc_@7As9*X0^>n;OAAzz^f@ALr5sC&CD#(|0}8#^g}`DFFg8oS$3kI-a`g zfWazUU0t=T=CmYm?L-ue2hslmXA`ljy}CD!eMJi#$$J;1@&Y##LW|M8k7pK!`qTIc)BXS6CfJ%=-7` z)p>3W6zPaEOXp&Lfw-7fFVb>r3a=uD zF0Lwvr->{dIj#n?%bnf)7}Z%LWQqjVSxb*P{BW7ISe4M+cLU8G`Xsoa<6liZT(|K# zk-!+`F6pFqt@M2mB|o7J5+NSP!eZ;yuEoJ129wh6>=e>XQ)3lXkqgU}KHn}Bk|(1+ zDeqFq0OKDK@&JR%T(e9T^YB-$yROXTbh4T3C{Uf0C2N3ish z@%)5;3a8&ZYu$v80Z?FW4G!5~tj;vQ1#(r7H8wnExrVgDv|LBCjBajSSV<7mN6Efc z-JSDvMFpRfC@@m}Nt7}zaK=@&0-EaEDDwo>OvZIcARVJ4lVjFU*X8#rD24nf3y1<& zNbl%2p%(YKTRCw&8-v_0U)Ju~a?TiPeTQ=z`{-+kl61)|gH!|=heMv%5lmZ*cH z4uz^Fy`l5mRZiQjj!I%7gfq8(ykPfL@#}{lVa3^HwQBXzZ?qVm%rG*GAGLN2(2iQT z6i?9*KAx5+ZJyTVg%8gLw@*T-0?WqdajpSPwlrztRn`Lf#|X;Tj2~L}%_YmLzIyh> zHU<>dz}!w;iBxjT%)Rh^GzTawLjEn9{EnDrh10L~03dsShB_n81;xMYOOe3Am^tqR zKC~2?D#%M_etRU-D@kb%Dglg%00N}?j2TZdb6DJU$tqjVJjzU`goG6NM^u*)^x&N= z+sJgVJU8hGA4>v=BxCo*9EFi^p`RBG;vHDpsF)Wvy55ecYKOWzfI@$Z0sskjUL&KV zR)&bAPcrel_}PQy9ceFUE0FvfY}#AM^$YL2b5rY{kicP~wCN>I|Jw9M%m@Z4JK+{{b525S6%lp~mT<${4#RIi`?p*Ns2I`pE0}gUo<8IR&W+>6%On zEMron<#@SBas6ENjT^jd!!}lIdCF;I3YG6(#Lu3yT3*wVY#Zm1VWIUA75(w-;}6GY zm|lK&Rh)`5LfK~}gMNzn`0i#j{rCQyHwtMCbQO>h0$N$lu1_sQd8*Z<{N06vJl5WW zwYF4H*0}OKIaQ9@+F#?iqu6F4dfwskIHr@HQqYemljnw;`5~ldSFl`Q8M?odt$GSG z93pBCe}K(~-7!M=n}XV*VxfI%Rz_gax9%sV=Ppw&xO`%3W0cq@1*%;z7fuIfqdoK_ zI9LM7xxXqB9h$BoOM*e$F#H=v8j0pQSyRv|#~hUvMp;0w{bs0APj_=AI5}WDw=O&@M(t5ot*v?`6wZ!!Ngs@fJ;~<$jYW0W*aMO^~4)S zIXMB5)9^Y83B~F#9G5wge#CqQe1jZ2*tRMjUbC;!nit3)hbaDq+z&O^sX3t zgFvVHW(a2trY+kpf$RmyHZP-3{3x7*EM$|W9owFoK>DSx6XX2ikbEvK@2)=1-TWjW zSB7yVE*5k_{gF{G+q;Sr-HY0c=o1dQjwAsFKpVQd_M-(F>%rQWNF;ljHbz9(sXH=B zLU+I=M0Hwjl-U`we+mXT zxDT$eD&@9CbnPpD4TwhMJG03UNqw=py+aDpI`1u(!}Hnr%gt$*2yLTC6dO4P)R{g%`iZ7$nnc~hXfeA3dXkO&c_w1_-q zPN_C0SWZi@?V@6N5ECAm*qI{{H@ecb3$!(g3>w#q1PQ;(ZJ(JdkAjU47RgWPicxQ1|}raJvFf!Hg=NRYi@0B4w&gbx>)_n%z@r#-IU ziS^R*gu0bhc-9~|G^Zn=RJlnS+p}y@4;l3T0Sh$KhhgLt%HmGB*r#IjF}qnO8oU_- z@__DT<5)*Ox=ieuqh9JC0_@W^lw5qB6mTh>x<{aBgboUg74fhmJg+3{z|X$! zwGCqtSo+A(k9kWP%o)ebY3*phvA@4BU^P-1$HG>}!=-OvzeFY!E;-x6935`qiY*uY z|C_a+3c)89td-Q8Y0k%B-%31Cf$0LI1904JwA={t->X}NAk}vNNQg@ zflwyj-C${>BHd#@N`*oeoC3 z6j?mG!dv3cX;Me45s1tX0R`N0xkBv@mji?R3P{Na#@1+Kqt8|W$B_G$Dn`&lcBKnu z1Uh#j*i!RJ>u+cvn5z0*<70-RT$3w^?+5lXlSJTZ17g)!6BZd|&;qJTUL9*vbX7;Y zR1HL~fI2AlHdrBDF%fydlJqdBM_?$a?*-%@=`H$B0CS)p0U~~LQqCQ712OaGFRqYx z+d0^SFS+hfvvYWVwP+0?u)A!@6^9@K@OrTOZ$=zB?ceR|!_YQqR_?J5Gg;03yHhkZ^ca6~LB)q>PB+KKXjTCy!hM8Y zKph+ZbXnYEH@n>ljCLqnVkg;!h~H{(Sw8EJ6^iwDa%Q&S;Feud>i=rmJ#gzW3zZY= z2qJ220OcEGhWKOcbM-PH-~O-=9a{~@>UX|MLK9zfrx&KpS^)Wh7ZrE&mW*OST}7l@ z1(@$~Kw5NnDyAv{7r+jeBqkM+)aHo|PZVM(`Hh?h&Kasodu64zUEd*=7YAHT!2BMd zB?Po_BQK15S3@m@tWt^F7{sF78C(vWqVAoA9YE9+vu6dG96mr&D>>3G5zkyDE><#9Yc5tJ5kV&~(q4j>a00l?dumk|&47e!{ z2}3xG?_e>NoD&XPirOmBdNBmXgsHER@8u&d_i7%4N1-H1YoiPFXmE5OVwcqGhbiDQ zN$TT5`@O*kr^zpcq9gk!lt6RmUrt7Q@0ie%FYmEopEn0Bw{FhbYvyIcfwa2(t1%SJ z8K@#t@*^;B=ybjut}aEpmdnTi_pt49F*}uQyohjEbzgi>|8gY>=d>LrU)Bw()8_?rIt{bqu zmrhna#p^BawX+Rp!&lg|x28<;%E#>jZdPHH*CB9H?kgH zmwyo({q4dCQp9x5l&nW|g|pAFSqY*(Q1SV}fr>ofd)2+3pNlZh=%N9((sNOnjymYR z{QKPqNYaPi2ldZP08AZ6Effgc(8mFCX>-gJl2oPzt$hS|66jN<)SKR9(yKcjA->ye zQS#Bh%Pj}PtGgS5x)sMS2j*{`_TJ&%(eA+>l+yjbAAZl@uz@~)iBCGZ8g*QS#0I3u z&KgHQB7EZ*NkJ_jDbHZfnEbECE7^lsg7(Y!BdE?Li;F+0kr!2p-mlWG|CR%_X$Mpu zYVSuUu6QC{nYxaV(Jk?1z~tG9gA`a(nt^E8LD{~91JrQdD}Y&wtj1#pwqh|+s0U_7 zrI*QU=_j*z!$|)U_!D#Bw6ETUjwm5=s*$fT2p`(C&nWDv zXG*g}CLry$V3kT}v5+8p1(2m}*8I5{0fko~I_|X*wuQfbQIVe0rwbN2uLdfmJ2NRu z6Kv-Qhw_#d8xOSD2wR9K?tqQ0c*JTIjDgrTURpvfwIMqfRDwjYX|=>&-!bQ5;sIgE z?nQBY(LHW0z$5`30rhVX5|#?^yK(HO0!#qLIJqW=A*83Z1{SL4$HD2)p_B_QT#(gE z#_#xRrH#4osU`wDQA-(888Aks!v$F__z60-AjDCS|8j4)}N&L-@|3;P@w*$W; zmt>*i))ycFc}ZBOFJ#zK72q1w0bJOm-+%cPBw$R?0u4g_e*+xiB|v3hC(}Q{1qyWJ zn%tJrqZ^DS@g=d%M^8vWDEVX67+p<)PQ&KMsFN+lgM$8&~NY7k*?zMq-Ij<*~|nV8x%; z7r>afh!@T$E{(SG>80AT{|B*PI4`cgI8W-gvPzdd-~mG?uXMce!aEN}Q!8MtkxEZZ z?1p|q$K33arn{|e%SN!`}eLTQcq$S(5Y_0m@O6^I88`POaZa7w&QL~ z5)Q2qDGLnF(e#{b|2U(z`l^*i~Nx|3Nxz4bh>sDBaPYMkKw0m&F4 zoqCM~oq>yn`}ZcP`d3<^(S7vaq}B`o9Ct8juErfBNGH}r4@)Ep-gp|eecwWj6K4>| zrYs}4&shGhI~cV7fP*2=njO&6*u+EI;2BJ^k@Jn;yUT$IOBf*|ryZC?Om0i;7?&ipmYAB>9WN>dTZ9M+U{ z4`fFi$=o@A@{`1R`dH*70O(+L%I6WNOfE4iWEuj@7D`^HecY(FFf9~r$ABK8sV$b> zi)hY|izS}?QGzjU=cyu{pyxhSHCTG`3ksvr&Sb?UmPsmmQ}lJmsnB!ZL|Op0v%VO7 zv#kRp43+IXl~g~r^HC8M@43q^t@PV@Dxm^z=c7KiR+BkS7&lVAZftKSBU6R=Y8?u` z^MT2z7|G>B4^wiO|6fQT8b45@*V{PbU#DqE+)z2}VW{@?JVn&O7pA}&A2&zH_I!3k zQ_`nkn7hCYjq8@CH5EUW0Snu)Y_l{;W2qdpvyZ%&q5+cmVr(OaY8{iE*Og46Op4;u zMOaD+2C0b!qi~Pp&=gukp^Y;pP#+$EPusgO99stG%A~4gYl>0PluW|UFaf<_438K9 z1Q-9PqSQM^!4vvpBwAz0G+_YOjxP5_uVA$*XkmrmE0WT$ov3BYkL-@u_+&6z-6B+; zQ19N|+8y0;zCtv-(4eL~q^`fdVJKQ|3RcNi=g%rQofQ}6ZXbj~CE34lZh#`YcJS6E zdg9L)L)oD)ODrD%`4n`$K)+P%3MiP8ypbKa)yxE3PrM~@UL&`phv`|K4`5M1HZon~ z2pyC=)Nv!a09Qq)U#(P>*&rWFl8n+-3QC1M8}5Kt`hlHRBYuPzJ`{#_0c=oC9KUK~ zR*yhn7Rg4GjQ(2AfjdL-8UdwVHx_O_1 z$+$;7@AZ>-UP`7RECk=SsgjffGLA_%vDEW1mXtr4T^VxDuXjrY`rsaJ@sa~%1KBQ$ z$f~$O2_o6of-RI|z$B7E%8`b+`6*B5IHFcZ@K$a^Q(77jzErA0S82P~Al(n(1yo8c zHy}_EID0#{Q%Zo9EzpXjo%H_`a#GU`mU8-J`!t znn9O<42tn+4P3a=Nkf*~-i?NXq6IThRcOR-Aa6jQZ{d z_A(tA#C&>gxIq=HF0oGA8Nvc$1qw8yiU8*W?5fMz%(IDPhsHVG9n1_APeOy1AbJ=) zY&|k^(#1Kmcq=kVyB(B}PM2^K{qfxr9lyFj&OF%TS8}S-9V!DYkqs2OiNRVgAHm$7 zoPx(gCglz|&{b>d@gTdcxj!vuyEj5V&yvJD97JT>r3yo7t8K`=4*XI<6EM9O!z&c@ zl+Y0xW4$Wbzmg69s3_6qG;Zm!M|7!Q3?~9TcID2>lRfbRzkzJ?vmezl>}e1hEDdo; zN#;D3>F5`Ew=d$O#)3sGRYw5^3=ilP3^rGwXwPwg3Sl?$1}Z`2;8+h8e$rhWcQ4m_ z1W$Vggm-p#Z-u4o4R}&O7V|Qi;PfY7ZM|nuC-610xi-f)eVY#$)(d6pi9=>zIhp4K z6-Z1#nBB3k$_*J z=n&BXpPxNhhswnXNLShaG+Vrmr_mFbh0sKX^9O($cFf0oMld32rQj;& zP>LSft!#2I^G5{}9Q6oi_WVXZ0=v@Q`T76(<@m#=;?oajEieD&z)bPz$k&Z7t2mMS z(l}ERw6iYv;Ec>A1Onlc`(0I1gS(xGfQa~8@mJG_4~kQ;f86;s$ia3YUJ!vkD+^Lj!SeH@qz2&UUUVnPQdDOa z8xJtDFcthb5QZAUx-yD<1Qgi|!xbZ}xOHfx7|}QA(+Fq0yqHQNvo&ZOms*EGxJ)5; zjMn9pM0Zq-4f1~}4BK;ML-?m77=aWlx9pm4QPH4r3$u>q|26S$3Fp!m zH;HzWjSOZju){W+GU0%VPjeH?h9tNoYVX=R$lajs148$te?Q`%-eV5?zn9r#T(alB z;eE@|Af?tNjTKt!(oE)>itxd>*8jz!c-^>LKWh!bRNGMfwHNyp#q-lm})Rl6uWQ%-%v0TUT=qeJsx$JwVaB`>bk`5Yzjfi0euo*&nx*;s#2m)Q9Cr1~mdJ z7PfbJFnwTbhQo|j3cBP$C8fZ&Q`ldvYIJJLo_gs!mo-XjUq~5O8RF;fRGmm)Gek?m z3Dj}EZ;vlOkw@la2(^0d+xGsC|KP7?je7cO6$Cv~2It7AM`Kp}F2B0r&8u;4Fo2~8 ztJJ#>wci(xupEq)&rdrmt|HoqlVW~7{SlP)DQ21se;qECq$}5gLAZ79!p5oIlQ3A# zx2mBoETx`oI6l9|x`Xzf?sA*3qq{X}2wKwwP+PoE;7+B=^n;$m_!)x}C;337cKQw} zfWP)8y0Ql5F5Td`aH0#Dr3gDPT-odjj4P{BZ;ijk83R+%T*%*Wsg(EzD==Siz(H5l zW?2O7lUC^NkZPZ9odrMnNIaA8MzVzO4*T~a`OVD82nH2wK%f~Pv>P4ftA*==u)ca# z*~xo!SM{zSfiKoyWpbL#&}Ok#Joe&rdE94Sk4X$H@AOeZpHY!S7v9In+iFraj3R@n~5BT=zlQye#kTjSW!_~qmC9ef$wmB6Un|O!<)mz z=~C!hgO>=nuEciROMmmRVPciqI}gL&pGv3DHE}QEZg$n~+&T?+!O7if+hbQ8#fBBr z5*P(DKu(naIw;m*G+qxgPR0blmd1+5I0y|O8(i|!^Fx;lV4v#BS*V7$*cvnhJf>A< zHWlii5wT-A^O%rxWx^(kE!YGM!@=9!=oyDxqD|wL*yPbtz!qGnsa7#~V;(YQdsodD zecUaD`y-5x6SA~?AOqr}W>&DzsJo&RPNl83!J0DufTDSADTI|Px zt;);X4#((}vcQqtKR+o6eH&Cb`W|Wh;!ka?#6~798xO$5S2H9?FcYdvBV_XSuD}+@ zP#pcT1Pkg?3NJK;nsc>xjhT5u{+_dQrYCvm0uKDK%rm>Dz8EBaXcy%(BsO{$Pqvoi zXwtPGz)X0lU5rxFU?j>L7)lrW0-*7w#7n{k?AZuH)mFwZCJM7*p6_&~ZI(qZZp34H zOrnJL<6-(B$`YUWS!hHYUMmHU4YnwL6^Kl516f@W$gVN#bIG`HP(v~f{-(<*L3(ri z+9uXV2Gw&ix3#Q4*t{z3uTBR8q8X$a{?zL&PIP!~7d*VAW6@R5aKXGNZ9)$+;GA#y z)#C4x%fa3G1Ds(qB3y{Z4a^9dEJ652S`ljCX%75Z-AAwSGm+Ga& z9gDj@g*6bNzT@4p?SB0t9Ah!!_cGx%RED2>8sc18rFK5dR>~yS(kYgXvD~uR`FBzl8D+hPb4*tptXapV`1jdH*Vgj+@SvIRU~pS zn$j$y*6uRpSXrBF!Jj{#eCh(ei;_W?3zuFdAY)>ZyB2L@Kb^*!hA+B-5|o|d@vpE1 z6>#%(Iv9S&RJz_oY_(pyqYLO}{tO>Rek2t7sFs3G5&4PgRvog8G8AEPgm^)qye9ho z>L7&Ib}L8R-|m|&%C-p8Qp^;Us}n(cq%iC=f4cX8b$XcFP(Z7Dp$n%s?#J>(&S0&n z1XxQr+lC6Dl0iCec01Aus!tUw}0c^$Qj)vGv(m4_CJP;S+Sb^ zIh@j~AtfN^UnFD$K@(!Jmr+vkP^+b{@Z`BdkX(GHGyc-N4*RCL0#DO1JpoT zAMaM=8>ksT0WGSJKrRtF9tfvgY?Le7bk>D@(I-Q;`VnSC%$6Z}YjV^HN8j`OH^fl`Q_wOmVolXJHBxC&_BYRLLd!WL)(vY<_u5eFY7jwE)th_Je zXAd$-$vxmkpM2l?;fsphSYEy_b5!uo%4ZUXq#3GZHnxzDppm|?Z{uBAF4geyZ+{E_ z`XAw6;pg6*d@A0aeLNOlm%Goq7PT%Rb2NXPNwGG3ut9O2aRkOmVGru~Mr+V11Xj>6 zfw6y1*h4qfmV8ZEMr%V}sm89JcL$-9?R0rMwRRD*AJj=|4%5salz7pS8s}2WVPTZ? z@J>J|ssQWGRl-up7?4U`Od{1SUzxtw0kdyBr@4XfQJ42=0`WBrJWHJpBa+@<1kttB z8w~0~C}s`I3Es8FnUSMz;R=&$m1Ip-pj$sdcM^c>*)N}D1hr>iwvB;VT7WgaI2;%W zFqR5o^SS`y1yua!kPTjtx|O_m4aU(ie1LK&V7BiRot-Eu#t~Dku&y)ZT7fJ* zeiZVqd(p#`H!`HkEJ|GMa~TzvDDSk8_m21v5r94eH?ecpi=;hjUN76(T!YvM;{mN( zs}?lxfsddf5d4~}wzglA&{4`@PnT!Q>2Bxn;HZ1HqS*hY~8U&29F;m4G zM@q*Ib}8+{8pjB!n7<}!@ca!3>@>t2xFS;64ybE6|9dZormMJ%WqvFO47kW@WZ3@%I1xiL zv_q3ddodf2i69ma{aZ1S`Jhyex$8O2s46mfcp zz18Q~x9)+RM(gG>o+u6XJi7{g?0o_G_~6J}p7p3-LGfA0Qud28(V>-p{RO5F&oStM zdI(g0`6r}@b!Nh{^`*FRt^+9(M(Ls0ftjTkI3xqY?yyxLKyVWLuYxv#+K3X#e0&E= zlUh5s8!-L@q#0V_-+Q=4e4hq&(3=K-PXtyYVAR@runXWzY$S6Km;TgsG>#q2@06KeJh&&g5u&GtCXkaroo zz?PT8rySfzn{9fPc(l zNQ&LCEt!DT*;3`+Utg*c@vCI0vYm+}uzHfV9I996(g(YpkJ^$BAD`-$nzsv}SxA8l z{;v?_6zL+k*I$f;b51HW0>5O|?z4@lj_TDy!FCqvL43@Ka4&fHn(#v;VwX6pn9W5Y zMJ&w&E;Zsen4A+~N6Nb-q6NO-n7f)y)#7}rhA z8Dgl)0%%M#pgTFeS=~B&7dJt)J6Ku3h^t@8p2rV3{cp+I~NkUs$xk?zt0m9@M#3bUHZ-@n#x1|ndR0zbQKr3YC7~qlD zl`&XxcR^KjDx1u&^X>to%(5|;^YN%ZWFeuBjmb_YtKfmYVf~i7le;li6_uA=WW`Qi z%57hT<#^lO_kt=^=mCFIObL6Gi+c|_yxaX@_Bl**$9cdPs;X_6Xe_F>Q;z5=~(TGv9|aWerOIN+JNYetwx)Ha3!!YPD3#jhWJ zY`k}0?^dv^Aw5($KF1cb@L7<)WGNj%Cp!f4&Mfa;V-$*7s>Fe`50h32A?gDKDg7~{ zPa273%cVtX`ZF*HEAJ)fgQ$EO1maJ$y3a!{K)ZyE;la(?RSsbV0b`jTQh41xCmL2# z<}l}7mYfr_;z*ANN^ZctiDuiWVz9e6Ofu7J^L^`THG6Q=#SF@~20cf;68l0}9H|&) z>z*Tt;2!2Jfzi16Q%y;XZx2p`e2}pG+%spEa(6i?z6vdPM|-^(EbC_Lam&0~oRlfa zhvQl97A?`IMBF4ob}f-QY9Z}JMF!}^=>Xv_Cb#ISR^nq9)<=TPD&ABH_xTgPFCj|l zOY0xNHODix*aPN~vtgU>Q)$RK&wqC^=hzwcnAvhgmS$M+ zO}qf3<*G*Pk_{0sW|*gu@iO{ZYYWAh*xN)7Cku#W@pGqV<{Am|2hA>F3Ijlnp>iwh zk`#(MCj2GKrWqcCOOGKc5Ok22TXjNKo?bK5U;SZ+WpUw3Jx3l!MfTL)YAu=e?iki6JE~#D`XvzFI6_5gUA>58y93Mi;cguD@zV-SqKIKy&42z1S9H6FzsVpST69C=f%t^K-$v z{rm2xpFX~k(=N2p!wVG0FM1DTiXjbr7%m7v7Qk725lFjG1JUq5WXns=64C8G>xnXL z8+Zeaq9|D+fJH1ggUIC1CznO{w@(<11Q6+=zntQ4^djVJ;Y+H2%EV{AGJ4EP1QH9| zb7v6!im{3)jvv1NxFhN%{usZIjHC7E@QZ@F4;-EYb`zD8G5J=1se_5KI7R_ezm@&;kNtfhW_-^O#@n#U{h>b}L1%2XfP@0WEVlcgsZU!hF$sZQ{tEMRU|ABv zJ)1u*cd{%DgL3TESxPYcu(GFOsz3UrPTi zVH=*fHc_Z0>WD6arg1HBM3qX>{fvVMZvgyT59DSacpt-VmMXYRWOlbAtHM}NlKX3S z1D765UMDr>f}+L-WF%z4cpewO?{zwSTx?3>NrEjb#e-O=HENLM{g8%(ModVF1}qyJ z=^qD0iVi=Gly@)voXG5qf&VogyFA%Q99jQ`%w{HrmPebmHbZLDzId$D*Kg^qQgF=1Jl3S%}ctVzI(CF7#-IJQ=m{$oVKRJhaeGSBW@Vq~Vc{yN=O1S9mVNjd*`Vmm#iM)?8?Z#{r0w*ieZ7f{^-?~} z@|&hIh8nGaHp~+kjC$6FfVdLVEWHx6A!L=9HbJch=sEfSMB2=6nUY6ISOOj@m`AuQKcJ{@xd z3M4yu_D!ry^#iWVpg2JcGn-t{{-~L3;PnR59e>niW)(uE#z#7u(bjPn6;?czRIJ_H z_mKRpgvz7!p1$L;%`@ zAy}Z)DX$x>dAp?ggfYjY@G!0;`ZBqJ4nrRW(rdhm#*=(GFV1l=T7J+$IC!YWnxd1# z~TtdY>AXnqrRpHdN+1lIh z%TQ*RBM~l#?LL;1+;p#~O46Zapel)$oFx|U0wsjiKO)wa{&|;tqAv+qg}(wpMIEBL z=kGoh=Te)b!IYEku4~2I)}gwGF0qx{dAS;|>V_-=Cjh>1g@qu%zz%eHQ+luy7(CT$igt~BVu-fl^#)g zS7}UcWhzD6cc|J%FjYwd@hbi87(QQ9areNDQH!4VV$c&cR+mJ`jwm znCa|6d2+HPbM9OgtHP7orUb)j%}90=V95Z!BHgwu{jmkZFOb?P&WL8$!S_&k2Q}EJ z!;-r-4XFK5@8`ZqNN()m`{@cZ*m<~Oae#=W_~FD0l2 zs0_TA>^v|A4Nwt=^#4@TGg@BWT}^tc#pp9{_#YS(=QP9+40why{ykQaQw*^`hF@IC znA0d|NS)HCnH0)AMR@UqBqS1QfDLMyMRDSCe(APn$r<#fPw-?HL$4qB`iFm^%f02Mk zO^IYN)Yh&&XvzYMCR_IfRpT&okBTi~L!8GGfB_c^_71jAuA8cRl>^pJ2dFJlZFG7j zt?YZ#;b-daAh7!l7%ZR&AO%9pJDuG8aCeP<-{{rXT ziUibJ|t&jt|=jZplaOfYznWEpSzer`>c!Au6{{d*N z8eAx>n)|H8_yF^5?+{w?DlvEp*cyxB9HJ1AM4o6XC72UZLBQ zOl#UF0)8_jJm*I?A-@ME29%>+bUO9CG&yzpanHdl77+OomP>%`UVPe(nO+tz4!)vsizqBMBufAt(itDd>c$wpw&bsrpi?= zJCvg+kiD5BxV%QB$W{lg9%Jh{O2dQU3>f?8>$&6nn8Ps__&7jW2c{!WBC3Pqnerp7 z02+Vln#eJ#WP!HpBwy6N=K9oIU+9oP$pK@BmYgk| zp~FjHioFHe6gcq0l#hg&h11xOP=&P7&Op#dO)RLI|(0sv-~27Vx|q zG_lBH^|q+EWzt)eEg(x&bojLgoC?&Eze65d$5LT0347#&YTb=Sfg?5pSdUwbI zQK3FP($S|F;023~yV$Y6K}vruqS4|_V13JtBWX0B1 zh*geQ_MC4vMI|Ect=B1rfZXx*;wCYzfu;2tx^Y}Oa^~QW;r;r^Z-CDaK|fQQoY{Qf zO66Sz8?=P5u~{QF!TF@+X}egd($~e@j0d}g1%8c`jHn>|m$WyqyNfD1ag{lrOJ*Q0 z%OMpD#j4dM`yw%k@4*{*ENwmD!9E__>k4=5z>r7IebaqQ)Hkkyu?Z*Il}q_c4F~Kh zI!v+Zn%o8#)*YaM8WVa?&qnR;+2{z{uV8{aPXo*@>e|**vg}>6Hb7=f>w0bhBSKuL zdr)!5Oa8b_8a0mFSFbeK#sALkIM0Zu7=kLZspF3LRn7L)X11@CwGg579B^5&>@9!N zp^ir;QHO3aL=a~Ei?!ooLO{Zjp(m}1D9{fq2emNVcQm$&lpc-Dwa%Kna)(ys_Sf5V zbzvBxS?Q@sv!gVT+!ACdsA%Pj8>1Hm8aKsalj)P+TQkrTVdC_|o{bZyAIBwe%L478 zfzn}xg)HVi3VZ8HxKfrsMdCL`Q48W0zEkNx{zK6%o-OAz<8+28Tg8di=SX^B5Xanr zPvt1v(NmSH8&!xU+=kNiOB$w8aYqlcj3E+B>8wNgDfUWmiZbxf0fmLq6I6%qY*jg!>?@t^_$M8Z)moVFKv^yF%JlN&HK5I%8>?O zdYb~N4A62@kX7=G4_&2{c-o0#Yx3hq$;$nBie(y zk0DPYe1zqJ-MOjiiN%ir@6JwL9ErGQqigFDWmP#51 zOTzr9^%s^(xKU0(NKK<0;op;maHi1&(QjgOA7>k&4^( zL$uYkm2I650L96#%STS5&AJgA_2DLttDCX$lstipZqa_FShMMYm9U&1QE-(eo~BS> z>2E&GL!X25diB}7QQ^hb4ru|B@2OZvj8oxSuB)Xnf| zCXRbTnv8cpvVp~JW%IT&21edpMb7`YINj^iHE*sFy|29-`RBqyl?%{My0B@;3TyI? z?HzFs873wVse`m6>1u|y#nBWQzo>I*c=D9|s#(MF0I(jWf7rl-|M&lkLWHVcUSGZq zK~E4~hI#0!b|Jyj6Q!-TE}?zZmyiT2oXBZB_{nJJ50i(jvaiH(KHJFr|C+b8oh5Jp z2x8+Q!qhRMDAc@q(-lcPm`{4$8!v|_**MKXjSCR#4rZWT_WPi8do@MQ&{Ti^-3#_O zP}tcmu=KnlXw&H+<|EQSO{h?nBU?X)BT}G3xQxhQe}CU3df_-Sp5Di{k~3CvwtB{d z1o=^!SG!5e2BnOyr;o6Pos03#rpWr)H&``w)2QXr*GVw_x5iwufT4K|%GPShENk+` z#Nbz}Db=<-(&f?_Lonv2C$1N{H2}gr!3mzvaPT-W96(YcpuL?7R}t8mqu z2Edea2tXO9P|dKxSO1L6Om0W`;%6UdcNU-hIqIM+Q3Pe>GbuOdgZ9ItmIu8#5S0N< zlPlBKHz3qi8oQHIr4=*LsFl_#wJq2YXF|5zSecSlH9}7;p=Mc0z5`a&gl>nUn_EQ( z!}-c%ko<-u7Zr{b5U_O2fx^>x>8He^W!Wq^6L6fJ#2v53{srcFP#&*y<=W>g6-#|U zO(CQ^&xy999)H$h4^}#4Fq!G zz_;5{dC%RqZ_tCVl`H-29``G>O#IK@I+rqt4QubEb(GUTx-cl8aZCRassosk6J!%0 zy7u9|`}ZsKxQ@{>KnvJNKG{Rq&~xs-fhn=J0e*m81m*Mq0uT>Qjv*UHGy%F2uUw*| zy}xQh)0mo&FtD_^__vC%cjB%(lHw@N=ji|K{Uu07ppC9Txnu0q?mS?4p$%br{QV<2 z!qF0Slp&p9Ol7U1Q)W^5QnGIVkOSX?=FIu%GsJ&dKVKfdKR>?U=oMGdK{|*+LNis$ zDu3mLtk+Is)mC($^6EW2Nj640me0|`P#cs#Cbx@m4_urxOe^k*M`DFhiwNqBx0x$8 z^tLm4tZx_iYLNSX@4(JO3#fy#op3nq4@=`i#n4!y>Byj-9jV#}tfMkN(7P0t_*+&~ zK+l}rpn``Pz%zsHE(OXwiCNs7edA?wAjZzHVSqr7`y; zbRIM{np-~}8}d5^C6-o;Yv!3qo2@`4Hd(;l!((v4C%(TG^Y#v<4fT4o@O`MbkeIqR zDQ@4OIEi2k`5cmOd;Zr-9g=prVr7U=5;?fPbAbR~&~e*dyT7qvQX$p0zmQ}#q8|J% z)B_fHcRR7FX}bpakM)tA-XO$qhdOgwn>X4oMeY84F_d+1eH_vZlJyyex^InWv36D} z1AG-tE0H1DP}P_kbL%<)5t%r z9!2@n7vHPGtR**<v71gnMr_sSm63S~MHO9P_Fpx8tdE$gFkofp$diYw=^{rY}3 z8kmwQcHRV_D{0Ee(v(m)kQst=kf;3sQjAW8$^)lgDd%(68ZK+}A?p?yaK{o^( z^tmcL;_cH)tq09>C2WE!w@SG0W$L=?A}C!)G@$qk`Z<=U*vZX6Qi8E>4BM%BMODym zYHmubOn>e)nqx*JM5xPOeOX5ZW7@wXH-gd-5g?~)3@_dTnG7#T@Y$s#Dm!q0Z6l^7 zmaJ_AfLOkG_~1j~U5FiM??}nj#9~8!nm2;`+ZBe}azGBK_FPCkC1qBJk6xvpozIL* zt^2WClO*m)PAF-jao=!V#65_bE59gfL?G8^BTeXeu>Iq^$rS3qDB{UhdnxDGir0Z? zGF``weR>LNXwUA%5aC-6WMn6C!u~xuoPo9pB8t2f?#w!%tT7jxLSU;*xy+AJr;&_N z;~Mt5{V`DDo8c5fdSe-s;l{4%LpA^uk*;auSM;eL1&2tE+I_3NiwP#DpML6I6z@O2 z>FUwIJmFHXH43=m=`%eU-k6>*g;#Z(5*atWC&@8p4|PA1?7hw=4UN8)`+k6D4+Z z-#k$)Z-KA7T+PRMolrcl7YRi?M0Cox|K^q@5B*m{yb?GSZG&>v@e2*|2Ka3}6M6#% zU#7)ihHj%FY%MrRI64}z@`yB?eF*@J$lbg9j4me7K=4cXaB))7XF{ebTE!r2r`6E4 zb%xT84;SBul+sm5pZIZ-h)!Tr9mQ5I4HEn%+vTVPl6)V61PGdo?1ayjBj?OtTI>Dui6CjAIg$EejZJLeg zu!wNFI*`&ed^#0cfXmrui~dx23=IKz!Zdy4yp!tch|Fhv*8+YJ_Z89Pse`t|1n%R3HqGZ+RzuH69S`W6<!NqD?bsQtBI;T|#W?+Qu@v*G z^7&;P>;WLq%uPuwMLURhUi#6XbQ`6k4SylMz_C!Sr#U#V^60X6Km4a+mCaWLI8(DT zT077ya~N=TvE!BD%a}sCSiQjCeD~sSyPd-Wi01Qu;Eq75qV$A25Uu}Qz=8b?@d+6VYUt{vohTNHnTAyulIkPfBrY0NO9o%r?Drx`9RTYfvS&~A4$ z7=*WEWf=9Z8)Ngp(%ZDF^Aeo%KR!~lF&JZ@4sVzQz0GQ=+^3%S;qG&#uG+MeLjQW%o>pfBz zD!UN{BJx4OON906fSF+Lfkc3a)h?*?-XcwgFZxPv?eaV+sKOKzTpaqZZ(X5>7RF%)9fV-TL9| zpv4q&rWG`}B(bLa3?DM!!d#Z5?9V z>}&SAHlzR_C_#lOAF}d9k=-jKU?6}irY7h~)#*D*k|b)$pdJ0hQE(Pq$Lxx1md9fv zwTxA4=EcP>9Zd=@cY$wSFMdG!sXZ4uxsYrseT7{9e4x{&vwo7e#y zm*`-hWnJ3UX30>j2PaAwfR&351mNp>(;0>dajvQIURWFC^>p=1Hzv*TV}P(D6<9dM9}y$c$Ulo3 zuFsOFOeF+b#!ID4i2_wffoMk8uQ9HBXgwELQeJ-KWT%6((O$P3+FddZ^GWcs0!1L% za|;`C@u=Ga{04AlRhX7F2XhT?%s^0b2JmaUTUl55!C_taB!_qal@mQA-lTdfu+pdV%|ejR8H3QznNeGl*@eF+#xr zJ2?B2#R8R~6&Kb1Rjh-)`O8nBFoMSdGy}G691qEak%Ot=uvH7yh3BGza5{%g+f;!> z=#)jIL-MfsSO+di7y;-rDjo4;EG7?d4y|nfqG>ggrA^CsC8|U@0mcu@(>HuUscnbd zQqml;)hO)QlsYZq=(T;0O8%Jg>;zsayebT6Y)O17H!inRoB3l2{hjwmrL)n);>x6* zshbudd29NM(VP%@m74ghPm@>@Ac0*-OuMnsFvh>q(4Dx!zZeM%C;l<_#E42tRLclSvRAl7cRnva%EPY8nXw#ieYvEhG zXj0V=h>yz&31+b(SB;F%B|WGZXI~@wjMS6hsuWpdz4J!dPG0J*p-WbA`StEPRzj3% zHDbOih?js*h}fVUx}?JpL>`E*y*l#GH z@wM`A6}cK7IRQAMNcO9PaJy9PS?OyxiY!AGG&v&@pQt64nIUVhuo6c>rha z7L$MgS}uneca0FPM#*0C87(E{=~KRp*^nILU_0fE2CqcGcycFtgkU^1-*b0x%QA5i zxQe6o;VWV_Ot!|MacE+|R9WvrqrOtXBX>zB=-o^+bTd&4}C!$=EE7mR9{8ZWqTRJd{5kcp1R9BD|A zO+YU*lzCCE_(|#Kh3Ie&W+(+u`(L1J!l{d}+b&G4D2S#@T1S_v+d(AbRs=l4khNYP zBNwqENtS9dUmS8Hb6ec$&m`{~W-=wE2%z~D>JDlTnEr-{2is+tLS+={_cBSFDzJP! zcN98f5R~!EGG!NG4gAU{v;wiY%fD6V$K!>r%w`(7*-ZO`(Y<#28DLX6XQi^XpZ5K5 zi|#WUvkXyD#%bXgw-&=Iuw1pE;@fq3Y`$8Pu8ZU=LOo{VluoF+omkB6UJmJ3CW(b% zMnyw$EmWzVLuaWFSkOns8%26f&%yVh%A{6I-La?+?lGJlIF4`fgH6M|UDEbm<9Yj~ zbjaF6WyBZji@ZTd0YIh@EAp^sS8e9&2keNbmo;MzApY%B^V*_5O-llB zn1KP6e5DM+Q3bFkD6~jhlXz?{f+NTxBa$jI&y>JY=C^_WB(VdR+=N?9gdK48C zj;WD988Vhf*I?B~YUxrYTucSHpF#Z{fu`rqDSs-qI^To&GXJuTi9n4r2iBRGm#K{Gi+nJH(@+M1D@MSYJHKVFRMZTPGzl!E29Ma)^y+ejQHxlyyoJP( zD%V27^I7Oy$x}FU@UO@U@H?DasjNnltw2(r&yM3m{x>>j3vIgASlA@T@oCr>L#OPM zQ;$)1bL%~ZB?J*$q2apZUZdn2s-%m0MS$|ikH8w+WX;;UNz)?YxIv4U*M!rYs$D@c zd2v&C8+JLAMXaevsT-E0tj$+WKI_?CW67tn#G=?cHqkuABb-I!t;ulFqw1)})A)ka z@yKgb%r$0L1-x@!WF%pT%YP`SB<-Eix6Fb9J#0HcfZMk%lq7A>kS3y`c0Rt7oYo=+ zvYA5!Z|UQ+j&EF?X&+V+@KY8x>*yTv=N^p0x#P^^&dbUN#2Gw#P`f(LLs5~(%&ik_ zW%6%DgH=9R*SKINujncau4~P9GSQ&`(6^qfa0&U>I>|yIAp*7TcVq zxIED;L~=ab-_>*;T6S462KE>3j3{e1V&fzD2#xN_a?z;dNgm=6%*YId>!D(2(qr41 z_nt5cR(aC)3z=|?{+Ws4lZwBTLbo-#nqr-6H&(K;hhhUf{9-JQ49&G>!(65!9}~=( z{Ha}M@AEh4#jHXVPFo{PMEdJCOyD5nC%o^P8vL$JLwRJ;g zw!aesr%sSV8s7E0`_~H~Jo;&wkgL-%?gUcJ#faoOsKfQ1ZeCC+xgMzzCBQa#1~RE2I^fOil6T!VA{nsn-r- zB1q37W8Y9>a(G0Mt!0~fK(Z{3DAGAyDz)z?jMu=zUwwhHIEo$c6_gIt6-=|pHSSS# zEHE4H0j$jFXnETb;f(Qc3WYO%aLL4l^|jc(k~KUv+~zc~WY9oOg2PDNP4Nv3u8gUa zACSZLVp~y_7XA>#MifywFBL|I(4xF6$DVP89h*Q_)eeG#W|--aG7?`d1#t-087Vzj z+D&7uItEO3Yd0l5#!jvMvaT@xNMRv~MChoV$2aQGQ;BOb@r+1LnI#~pk5=b0rmzAjR4}9Z?DGI@Z?O4M%gh+0latengPk@yph7VYKU(5j z9XQg?c^|XLe?o^2;JVvYcR&D`ESKT|1s}+JNuQ+yD$(>*0H*w<@%nFOUYm>B!V9FS z$+@OFK&cW+I)X%KPj-QomH^l!28$ULJJGjQT(P|uE3vwDU>G#@9m`3WX^y=lvY6`e z^7zB%D`Hd*9@OqVSR{wt>EIKXz4)q1;$oS6JecTvDZI?J)1_G5-c7C$_PUJ0eqrs@ zKeZ9a5}s{jR>o3B83KjRIclf8mPuM;ceLV1s&p+@&rmmrTeIbiHc(R5Z8uk$>_~>tG%QIH9 zhd%mTrjm>0-OajzteAnvLImJBfO4cETG&|>C}_z&C#lM90|c+ApvMZxa}gxzjbZr6 z59>OKbrfq$?dss9fD$#H^#&S5@Ijo*s3uktCwmg23&!Xd%SyrFQ=ZB9J%5L8T6>~r ze->>gD$AHvQAO;E-f1+KltGWeZ=(Dnzy_4yw)iZ!tq0`o6K0=yL3-0V^aV47rIlt6 z&a~L0?!oEVXo_y8eXS(&ce$t7=iy|&`T`iKPDrA2U^EYOcMN-EbYjXfDsGSsu2Vyk z!vn%T$lFlaTXBo!DI0Ab%~>egxz zr=diQ)y<08+TB+Q?9K?JY$t;jTecxCu*&V z_M{f2rUIa)1U@(H;!Q5zX^U4AkFQ>(9Cu5xJ52rtgbMJZKc>_9VJBx=IAaCPM{pKKXgG#SQS)Gx_I|Ti-yZF z?}c+;X7Uuh*D|Z{J8`C5-+FG=vr1%hb?X)B7J1; z3G|syJMF#0y`$ZOy`%2g$p6P-sd=J63!mKQ;UY$DpLmam&NE9x6r>~M8bUNhyp?5T z*l*-q4xLkhTm}6}YqY!^{#_)%3fHgU9^1Js$t+&WXj$*;@Dty?*tx@`+PXH9JB*eO z?n$nL#XR@W-9uA9r7#fTsAqT&apk51IGY+xV<{!Yfv9d!rNa{h zGvKYn%lREzTtu3X6j%@&Md;akcHnq!cuwlvVFB>UUe~FA&*CZHGHdkAQkJ8g`hr1O zObKw5eZl?3i-a*iyrccV zQ4uXtK8S@8+ka~>ZvnQnSAN7dKGps;oKQ2o6ed9{%rR3%P-zf^cc*BI9R3>S0>o#2 z=~Q7a3(n?1k}TwI08k@Uesu>TCXY#9d)dekVvp0VZWqLUnowz_CBsyCs|zmv>Ltl< z`0MMLo(Vv1DTktUvY1h9-dv=BSGDosQHT$*ufe)D%wv<^#jCO;1FYtua=g)1jfQKiOaU|&Ui0Sr!8!%6?%u?cW&TsWJChWU^W;2v&`jDCSp6!S*B7zi>qcG|ImpO+Q}!@t>msI19d;Zqw>j z!d1-)_4>f(o6|!p@BfqFdp6b~krzpW+W` za>oG5(MRTi62p4*1LQn!c{H=YUEd>wqK|jin|mj6O519&D&H-|fv5%m_C5&g2{ryx z0cD+Y*K!PZ%WAg({}}wiON8tiU3k?}h^`!hb@zADQ4^{ogn_g+0_iw3?b?rxz?}LA zRZj^GqHSq9Qy2|Upf@D`Ut|Zusr5#M&lLp`wV<@!cn@PCbR|9|HXM9aV$+N)nCU_@ ze@U2>1GPZ+nhuu8Yfm9DrP6s$vwi2(>BkA5;^h9PUT<*%rI{tEV2hI;yp5CE!`D>P zm?&Wi={Q$L@SaR=wP9XI8d5wmUI-ZFe2O_?th$^dE(AGaPgi(~zl=NNVXHsfO{7TC zTvpAxiAuSpoblE(QpAZ=l{I_)K4-t)j}{PvH~8&xwLe1P^%@XIe9FMwbi9Vq_33ZR z1-=;5NGP=gMf%&x5Itt(WaBU@PB7{o6mrA6yj-epA44EjmV_I#ZQO^NzT$Mm0`L>a zwV~H^O`sOmZJoPo5n))+b_E_RLMkXLc7i9n+r)L)#-p6s% z%h$FZs0z$hyn7Cx$KNExv4?JFyn=lvErwTM3b$WeEuewYLfI953X|I-z)Qlwy6M&B zPu-)>>YhJPtc+IM+yaamCbXSH=%st!S*g=(NC7Qf!^6q3b|qSoNDT_5;NJ9k1VkxE z(g1nx)?B5U$OVIT6R5<98ZnJNO^Bh;fVo}r@k`D(A}tmZedP}tp3Fo#J!p;3AXJ*Nxm*`Ee9NJ3WIPO3_2Owhgcur>(d*|kwKh;e}V8g(F~4JEAJi4 zM^;55;9>DQTlI0O0R?uigg15zqdgeTNQ=3i8wya%j+l&C(L$1gr;)&}Rd^?8MuQkX0X+nbM?5A(aSlN<=zg9rqS|=a5PSa^;F937au%9Vg>^;0 zpw@7J%_lTR?ju++R{-X2M*{w1!Llf=oJFM4jP;1_qy#<}C5pC%UdV>U&wt4}IQOG* zS%h=bx+qPfimhhnjn#CPN!a7GX=Ph+-#~`BLUCpo<`E>`!dqxnk;aW(VFZgx_BzGh zDD*B>bNk&$CZXSY08izXSCk;8mNuQy-2Vu>EEAD0L1M*K6X?vf476p&j}rtQ;s3R+ zaVKGmF32ZG5AWyVv;6Z*%g>1YW%>_y7S_em>U*+uj+b;+-nTx8MDGzb9X|ny5sFQM zZz51c{Yj2hRR1w;@!f=_0fT%sTdij303k(!JtShu{6v7^>Xv=AZWgXd>G3kUSE^j! zo(jkLre+Tp<$mE^FD2=F1Z=%(r`&m}BXkYH^128X1<0EI7pbR4UQeZpyRAc5MFh7=C(fzXT=(t$eOL1weUkLY z2g#JDY{ZpVld6Ym@8I}($Al?6T>cf|yQjz%RF_pWI~_sL19=;_HMl$(|SVA-RAOt=A~0R-&-d69>^ z*EPktm^uB=i%iyjJ|5@yg+wY609xZAiw`{sU$rYpAO zfAoK`_x3T8UDushX=W_T_SlgfI?J`W>-H|KrL`lvtNLSlxMMEKnIhSm;i%m`q)3_G zVs%yZbaAS>npM?3GYrEh5O*zX=(S=nYc0Y6T7WDZ$J@>u)?z{KBSKZZPIY@)-uBrQd@44rm??YW*Gx1+%iaVRX zpoMFZ-rmNtYLS^=mB|+pHzE@rEcqvJ55s`fqw-$go2c0|zFoqJiKc`4Xkr6n^lzU6 zmu0MIld7haFG6bpAI2JtrkK7|-Xd#5Cnn*vmcg-z3da#|(B8pn5rE#heR`X*xkE2` zlH`EA1idgnHzd-=RJTD>T@l)&GPLuF{gxZwYy&=TtdwZpt($5h`YfBc#p)O=vDS!5 z=j{zVrf3;*pb=f|3LBP-6>Zn0O<~)e(Fu8?5wrG`8Wo zqvUM?X^<0~QrQDCM|GOUSfG8oKRg)17^^_loxy(26^p}I$>!Y&M zu@8q&noV9}cD?BRPGbY6snA6D>KYi~x*$D4SO`A5jj#Yrd`=cLT>?l*rX21F+blTB zZ524<5eX(l>lovksoM6e-WZIw+u}b}f=iE##w(@+$x2|nSJ8P+#7Z`eMkU^;Mzd&* z(vV+Au9bam?dIn8(zn=*56VCcBI4X6#Y%PGAW`?h&uI@iX-sU&{vJ$u==cQu!%58J z$RpxDb@M8bx&+*MhP53;d4$Q6*f$sl;}f95DzbZWGh%NJoV--CKNPkBMp08^#ERez zE%>YoUXPMJS(wU^8)2y)b0&?p2*eYDxwy5wXRGRiUueu1TMDk>5xjeukY#i`8I z7)T1RHGx;f_6KMcw3vh?K7m6L{3iX*2h%BL%&84$$C#qNfK(3r1wwCZ!5+@Mx(*c` zRWL=EmlSK5a5u&%B_@Wpx(q|#;JL9@XPranO{ou1u`{0{KS|EYWHdNb6|0l#9O5%7 z_~2CoqdyTFB+Ho>mdaSd6i|u|N=?XQV^}pOv=w=&*3@ePnL;+Mh}1ZaBb{jA@;+l` zMNH;$YqPfxTFcOCplomU=unr$XEd(@H~~1@X_PV>Gs_D%X50#j#&R6!L2vnXYZd*p zX1x_j?7(svpINIlQnkR9r7w=4TLL|5)5)upC^h9*gm1ks1993PdMF7SgCy$n)C6cDT@2imav)o+y<4Mk7ja3E<`(Rq zT9JwMv<>3vXDsY?B<9lIC^_9PrA|<;YAWOS#P{-~attvED$TX8?`IPmS(`-In;{h= zwGqCjfVm0QMWdqV1#bSm_87=x2TXI<8BYav5H@SXAK$)1s41uPhN*7ZU z_)WuBnXag`mxrv=bQ227ScA}+abUO805&lq59V}Yb4q!zS~{DmwCq?l;ruDOH8~~B zHOE(cIH)#!Oqu^an0M}8E@QIEMIio0G z1y^1zUlaI%2*S{o#%j zG1>QudZuc@Y#@rhK)uDJX0RHeN36{2tMEAa3Yc0G-Vj1W0DNK&qOX1urAJOe!ws5{ zfH9|U0hOR^H-%DMdwBbTY-Tn|BZ(_wssjvL+Lt|vQaJ#4eJ>618q#~sFkQh>ib(Ro zbA*(A)zXZ$PU5I*hOji7We?R}DfM|pJYx|jTATX3Y9qJ8sOyh)`7(JUt+yq~B9-zI zDYxMkRftPwyVzCa*bvZj#0WAD$G@^#5b|TGwd+b}Jer7U1BiOiPzb}`xZ2)^VWf4U zHs^Ij(3@2V zP8q~_G~z{@beJ|e*^9#WrG2%%S8qTa+^#nq^{*zq7m+F6hE*>0`Uoe>NG^@mR}Q9- zxIW4dfBGH7qKpb_zT(*Ng&kQeNCCbz^N|rO+{X^R9tGkx!~{37%y988Q4fnqIeRw~ zC*p#0sTzefu}CrzgLWGT@L@C1Z5zEw!nc4#qeMlJvrn(N>OJMu4P6h4e!oH5zHqx| zyJ+@uUl7r5d>4*H3Zx814m>K5V~!&Y%_13`Q&@0y3(JO%I%cdF<+20O8feRA_WS6- zXO-}-s5fXjhDhAd&WVyr6e%Uva!#`Ltb2*do9+8CCl!Tm(g}zdE6Ra&0QftWJiERq zRl}EQ>=(S-PytLv2V=^E3uU*7VGRt6%{8Bh)aL@kEggiBpF#vVbjX`H4e!VyJ;Jad zgrSg~qBJnkW7?7ke#0io+`#kSyk2iXhz}H?wmQye%dij{ARM{|CS3=?rNke6VG=qF zyzvHu9Fovbx+v#P63(^*!If3>s}KpM3$1I<)Eg-oZv;8gIW&h}ZZL8M$m_h@hr2C@ z$0=E1xCy=82bsbk`?QUC?$V_z2B~Hss=}i{lEB#E($K`0V@#U0>5#T;wevOtKx&Ji zNam>a)(_Vx&WA^N8f`RjX;WS%8+H_)0Hg6!V9${gegcUo!ZrvI6SG%X8TQ5q4ZBGl z`VP{UBvC(%IBDfl8x~cRBf#?}F=!A^Vi-A4TD{-D-5X45!<$V0qM;9r8D8yj?-FKn zFz!!;PE6>KC?PeY-qU*Qy8(JBngJgJz#un53czE!VZ#K*1>74LJjm$ex>;i}_#0>7 zuu(^xX-LyVUL^9FB!i341APB>6Md_QJQjP1YP#};#&AQiA7o-!q#Fa!lG zegIfg(%+J7u3MY6dyJCRm5(l`(+me0axRl0w=NiR3*Wop`i&qfPAJ;7V8K<)sY0n9 zkHf5r97BwLY&I#tpQWXutk;n_6o&~D2+yFi`~g?nlr%k{xf4gjlnDzR6rX^pN<O z)c~4k?#7(dd7^w9*omK-iF_A~g7?ydU;Buo&?SbLFhdW*OC#Nf3C3drw<~p(Qx#i_ z&8$4tH(z7XSw(ky z2$3d?T#7%>J06BUBbT1PvDLI}0M<)9Nww1c0D*nr2)~2qK6~x)otD*%>5F2v;S1*$ z4oCg25GX|=BL~%5bZ1kurME%cG~>rMOv#CjAsj9y6ULQO>tsTrnLyTqs?V5O2+y|! zXN@#jJ9G+DWQ-u%?sfHXLI-i&fw#cFAz^h!s=(Im$jQ24U}sEY?cJa7Rwb!}l31*% zZ_<~aeERXnTh|}E>L()4L7ze;shK3b2|in1Af?+`1E31(nc72f?hihMo*2)MRf|Au z<8~iL4(cHv2(NEBBNpvI21~z08%Cgnc(1(aR#bqjKs?3l-OKpcWG;D*-4ow`E=}4jp3%*p@R@2hXkq6ba{4U0x#8lk~SR%^Qna#=%M<@d%!Y zlr%_)M@MA_SeF{;E)CrqdOW& z?aIa>1MSRv^MJ1yHXbHpFrWtK(3v9C4tZEajG{N3a20A66pk21Rfq`#P8)SGB~Qf}xFE)s90eaY>Klrt`2C81SO8ZUhI?OZpXb|djFk>m+Nu18Yl+K>bULIDlO zxfXVp=hPiK!>aU)w$e;H=6z*n$moe^iSbtD!&c7U@&9zmqQAib6I?|H5BzUJDRYLTpfqCaZH>K8% zuiEVJRl45CLj>A*9w3K5D4mX<)Qkc?SBHaZHn!~r;kQ%iB0cZLLA*0TZPG$BD9 z(AFkNP=dQ4;0^hIIRHGv^8>pbBbI@LW1>u#dly1obtv_y!GbE6x~}L7B*tZ8Z&TY7 z1CAzQz0d^(6xHk+ky%Az)cAJBeF@t8Fg((Qk~(4pf=pl9RZ2P^Yi5R^0!d}8@J*~u z3%@Ex8c9OhM2G}Im74uzsj8HRn@zAmgDWKYM#Ap`hq!_po!Hy@3{lK2&0Jfttbhp7 z$bj_;bYF~$F0(7N;S@wfxt)E2Y-m7Q-B3Xc-VR9`VL*#XhElr%ujj5mUW%`=xF+<)F^P*?iI`i=6imJLS74h!)Ej>R!kotP&RO2R&v&z1^) z*C-Gd*X)(_g%=8kvaH?F=q4c62y9m*)VX9r1>u9ybC6(z{w0<@CQOU91C_V01gl!! zHvuxhE=d(P(!C5FAygrX0i;rqo^_H1g3SpNiriLl7iTtBo7H5aSb0Hv79(wXv^(1F z!FFWKs9e(#Pj8V!0<;7RPm98Q0`R+zJT3Z|@k9w2^WxZS|&NjB1{Y z4UL|07md>8UgDtUtBSr0YS&}S36jSMS_1HqphTJF!%OfXS9?A$kK=M~S=oAHACap? zPthKVom1lXrpc?l%adXva}Uks_tZD`=Bn{oS}I&K`8^6V3`P>A7FBb`<*k7Afc#N~ zjllk*RWYyF8X0gV`&{3=VtnT5VS_K5P&zWQE@^Hn@~XXRGDmaXAgvuI&?S%<4f-f9{Z9SyZDd4PGYj2YI95^o6LFC9KQosP-&nI6>t)5uZf z0kBHtoJ?o8DHfl6+o6Fm#DU45+z>r?89{8-;OPrP+5y``<8@|u!C%#mKh}~k+U@D> z)}!6-SB@O4u9!dw6ouClBn&7$I+b0hSlB8~R-3nx z2%ID&G0(;NqA{Bex`n5c@g&>B|&*Gj-Jp9r2i_8rkxb@Bis_GtG zA*vy|L1z@G&;Yq0W0lV@I>iJS$Q-&ZOJ*mrmi7+7j;}i-?qj`K5qvNj(Cw?Y!_k0l z7e)h8b5IXQrn@yeGbHvqg+2k+_LM;Yk&+sqhoqOagMCU*T02vO5Chr7oib$5iYWUS5Z%%A^>H?-y3ZPHw&`AlpvBOnjB08` z(Sl`(^$I+uy`ho#L((Uin_D-K8V<@uiCzb(B8VlTakIq6!&%L!P*ORn#44Zi1z>}% zN%H}WN7M~*zI0e_)LE4vTEDg413>(4#?jKaW@AWyI;1$ZXC zoc?3dO+qh5v2SJM$JiV6?ir3Isd&H;Tk>?ImPzLMi(-&jc_&ed(hyJr?*NeTVLSw9 zWO+}^bn1z#RLa<_>36AkDe+0f?RZSQ9xqX*NmOygm|LwTetR&)g7O3rjwxl^-+;)0 z804w;35Vq!%BLqc!G{7{J>js`&FgP!DgqA`W}=Ynhgc`oy>hs8(KE(wf>ao>o7 zvv=n}24}3F!eJyFAz@7Xkeclg_7eaWV3SAf0>0lA{>NOn3{B8jwMI4AlU{phawEdQ zcQWpTByeJ152|ldpxJaazmR`{6fdCdPb}=;z9J}Wt#UGrepeg@HHB`y3Z`VD#G(w@Cji)5c^ikug&y16(QN{E}$#kl!OUVrW<;&~WpKNZnu6^ZNvu2`q3qS-j)jO^O z?ZN)8^K|5|+Kk%@xFkguzetwM0{LT)GItGpQ}(QM#aOHtfqF%qt`URCd<{_fCXy;4 zv-1qd(2S%_MFsOEHIlsV)C@k;MtXLcDJfIP`y2}ot9!{{GCYH^dXD%deoS`FxwFZ= zovu}g#kHRB)OMD|f1yA%K?Eq_eM#7cy$%R(6d6N~1i*%~2r{Q>RPhw+&ut1}3L(K0 zDrWKchm_M3>9Gc#!){^Dw_8sg3?LL8bYPdmm@oRy<`kuc>AH`leg8{f7oZ-%k3kl1 z1%ri})qt~;@#><1R?xmaJtL1ZXznrO7fm>gaRO*Nf|-dDF8V!@1kFuc>F^lg7o-Hk z-g5LYw`yuA&o&0hSzq(>1L|fN!{72$%-Bw{1aHyJUixi9Or>5KK80O=u}fH1S9pq< z!g=4?;n8x&hPTY9f1LADk|2kxa_@-GG$Eg7l-_X-QCucBlQ1q8ZC!vT-;jdEI(P!4JCX$NA_HvS z>5ZRwtby>c+&;m1uJkkq2!$!Io>R zTp-<*P0CyWIOZY5hE1{|iBq`CQ@bIUSb{21fG`JA;irM#gS&8(vnRj|gRSSDzV-|U zjz4e13_}D1H%D)on`on9Ss<9+nXC(p6R~g7{v;?#VSr~v5IzaXU3@_}L0aH5%(#{G z`{7QgOS%d%yI3oePlcCE2eGx_)LVOWLS?L(x4qnny>>J#^91ZJECk@*iE!nu;f=8n z&f+)HqI?`l=;2$6tOJbTg*}OZqc1Kq8=F4sP!Hj9z-1Uh#H5!THHNUF$V}2bWIjp_ zLNOqd)VnbT=hVsHmU9bh2Lp3u0LryRcLjQDp3RqW2W9B5u5adxW}}>^FG* zbYCLKdUh$Yo5)xc;dpKb%zt*+hlg&P5l$vng9QIEQ5pu$lOE?XHLLGjx;ml^hDp0x zM%vNZ298Cp7wC@%BV-A~F9`7H2fWj!fj@9~XmM2x5$c&$oSf`ez(_-=(}TIxjvew5 zSnQby7KVJUgk*}0xH7mEwtxT=qiQx8fR-O;HqmY5d6^*BGo-)V(>VdTKHU)#j~C-H zGN>HQ2K2STLP?n)O2oJ%G_PFnBGo%}E8YI&#e=;Lqo+xX_Cnql8W$T?RP6LaXxky* za56Pq(vC9pl3$L*rU7!juX#k+Zo0v9+TybbUw(ixx4P(j3+4xCL>~9pDJlftzonfheq2VZ+)HZP@OlT$CfUyWvcA(&l49P@+ ziCFT(W^e#J)9FDY0>Km_V!j9mSo$~tIms0%fJ77cl%jIJ$2OsXc`uzqNuKmIE9W&; z9FT|^zl%|6Fd$Ziv#HmO-Gv%EEBec%fm%+pK$+!dZNQ6AL}deDp({X`AWK=|c4Bo- z3@~a9){L0m$ZUP4VyQj8(X2hae(m}ilcrrA-GEAQr+*uS!ZnaN#>ms0y5+Poo|Z|3 zr8KIAbxBnoJ{JbqL`BS4-xD5Gs_goxU?&jc6uM4xtkGLgdB=>f(i+f_bxxl3Y*FcBL6A+S;S2TVPipb4tHVaWxuY>z&neA3% zutcyEC0>0dvy7KAu}~r}6zrYls$2cnN^6}Cjp_v|D5BGbMH?O)aOx|9E)aMlg@&L` zCaWDYy8mSoOGwli==UJlzXUtmJw&r1e5A5abqYzs7bh%LZiYT%hIfC+L_B*p41&qx zxu7{)BzmF5!Twe>l$TR4D{N;oLOg5908!=Ro*@bSWDIqEGfHIpm(-q+t z4O^zQS7DN}(+3qWH+t642qx5DX0wlECt!L5UTi*l>FU#4>(2n$Br!n+pVuVR`eqxH zEYL!Kgisoy2h**A@IQSep+^Jy5TDb;qQ?N?X#B;883JtMMk?w$q9v4xTtb6dV@hG) zO3^JQ#uaKwMDI`1Kl)&b*Z~&D*5*g-gUWDM4#lK`mC8>5C}b}o0!V~}eKdQ?XWPm- z;_vi~PGyehxZthk3l&x&r6hPDfCWTf)7@cj+7F0QtTAJWc#@i2-VG~avhHci0K-fO zplwe@T_)+wITNL)M%&ypjJ68tR806>!$Xbsh;!0MAD7g_;z(e;>b3;R?(dvyv ziE^BiTQz;#XsZmYaWI~UJ$cu7#m~)1+DLe(P%TUlp#oQ}CvGdistE%m(vb3ez!@^e z@vu_N1A$%U33U|vs(1uZyGgqr$kPp1W%3-ceSR~Ki@2;z8h8@%v>R8c%}9cB(Ww_I zLj>l^4(^#$r7}q8ywpKe2!itxcU}ThBQjz?bCX1R0v}4S*?7stf_L)rQzobth=9k} zuOdj*L8sF*tTvFCBt|j*JN=C-)cm_5HWN(+)Wi4&sAN{t{0_2&38{GI6msd=oB}AD zOOp1yi^GEftlmdAVI@c&mtc_y6lXw5z(ow3rqY41noBYutOYj(2gu5 zv4_+yIY`X8KY6OHo>*}T-0-Rp?-k2vi`YEi`;1*})}vQBQ;6W(WRaPy#20@V+ z>Zax-naiKj7||2=g#$SU=dcFa4Wr({rK2Z3pw~jh01^2BwR>rOTO3v6N)hk=O#YS6v=Kj1(DrXU&A(F%Iejjm*&S&bcYnAB zLAT8eaqEDcY$TE<=&Av{9$_|f?J|iR(s804PhZ|+S;80sH3ho5C)>E?6ZYAwZ{eUE z3x{tgqJ@FTF~~IoY8B|PoVx{{2gLmKoCBE(fl51qxpA>tT%WA(A!t?qP{cttigJxM z3AmJrD5Wy;2~x(I(cRdb5VJ$*)af&}L*fA}@0rc$gav0ZXs5ub^t^_m4w~{%if=Sd zMOK2Anozw>`j#eAaube0=9M`OXEH~2f|TRR`sFwR-AoL*M5IfL-;1jc*95V(ERMuZ zfwvUl*{TshEK|*IUbN^Px1gG%yN`&nY^*`**TBqCj{&MloaIQT*mKpb!xqzlDRacG zla1{S5l?Z;L4>TVuE;%4@f@&!NpL7A@PU%7K-Un65D+lwq`qgC54D?7es6=oofs(U za|Ub8K1JIiaM+TBtSXnB^hC~T6#JHT5$gtHWM*!rN?Y=xE`;iYa9@(9!eSleSKPc*r)Aq}>l*&QVEUf6q25S!6Y9SZQ%x9Yt6i0`rO?^uXFy_3 z>2#sW>Wij1zX!CE@)2`v1cIl^z27r|$rIqIW?Sj$n#eGU-;?2b>uZk#G_9CwV{icX z(+lDvP8YG}hTz0B+6J(sE@vruOW``%Ypm@uRqeQch%DvC`xuqQ3DOY?&ox&IB{|hlo->PMQgLNWLVg3nJlg8o$W6re0g^nOucaPx zFWwPJDMwu!drLDaDF`H1Z%eGA<|f1e5|9MXdLm^{=-DI>hB;7JV{}KuRvW^U$t2;r zKv&+7l*EH`3nF$0)p>3~5c>kifB~EZ_(vuA5xUrWH+&&L*vv-P-QU3@3fEWed1U=7 zLO84=st^Ltf(*)R$MqIs(&1TU@Nh{2EQdD{$vGKoV<3SIV(_{l%>DW{Ot%Hd&?^Qg zfZzc$W1MbE2WR(Vb2e_Kn*jxe7Zyfc8O-j8c0p}T8jHw7VnVt>pSOp&Rpjf|yW+CD zYGTu;tQXW&RF@&nA{>aj$OQv_&!nYGXs$BFicKS;eqZ1?&oe#|sJAgBg_Qe_cABu? zrzs`f(s`MTPjhX02&t-2!ZAt-k$#;daO8fN@g|Mqo4x$$g%sW*D|Uh%yT@+OvOPrx zfY1b#9m^KTToV>1DL0|(thx292CWrM6a%u|9Dd2ENUVxu88+9-02Y`d+S`@odO}G| zBkx%z=1mcsY)8ti;D{J9J+~MV*J$-&y`gh&Rv?4e+aV^|hTuhnuTYH|qv+PHeisrp z2}F5gyzg+c5l}c1))S|;Oo(@aYC+f#AWtAKL%~Pc`^s0q(RZ69GOI;NWb~#UhcnIC z5ReIltB=^^3D<;scmmPLi2l|Yk_;(SFrvmKyVTkeYhcHgsX)lwNrcRR^g`dWjE9 z15i64_0qg11t!HdUI60TpMcU@;Z#VoV?X0^ltz3dv4$j%xo>HY_ul1JxDgfgK7djb)?9)UX&)2a&P+*JO(9$g@9L_XmnjZ z>4jjk|BQAjA{uMIlcREhNsLY;dUu&WsG?9Z7~ms||F0Pzk^1?|J-Tj>Y&Bp5d-L{MPdvXdM^POkc7EkUv;3tMvF1#?THc!;^h_$FlcTAde_FelCW+F z5hh+zCR3w4CBBVn!mrgsxz;E(M%tA1?$thQ=B-zg%94|O;*tjX{1$vZkn)J+jd=Z0 z0o*d zG4n{;u{B(+G5mxf$t_SLcvIlWCMv)pjN>L&G75f2DYrP2Wt%6QzqB?1EMAFFzspI-GNky2Kj2tg|PHaN`{o75MD z4K#{1!wV9Df)!pg5)=x>5bIt1vJeh{av(~mQr)CDzWVX?tR4hGNfGY)qLX9hiwLF% zZ(>9&rLTV%R+*zgqG^xcO1;)u|GPT<@2EH|k=DW{+XgdmCu+R|ApgjvP_l*^1Z()A zFkFcV-yD)I76(tu8VZ6v#mhzW*W^4(tge{%Neu7BJr~~h21+zeobi(}XbzTUuoG%A zY=gOV_QjN_4b3H(Zt+H9#|Vn)1YCfK$kBR)iN=bUD|K;fg#xwSi?Dv_Pn*MiV?$3- z#ZjG6%2*j%R3y}g;TKZ*uYF&$a-P}4?OotNYL1-1u8A zc_b2!MplJnATS5yQK7qx@TCG)cKIk=SP)>wSDmJfB!*g0>z+0BD^jMw=>@+)vPr<$!cMAOw9w^rJGh-&oUh+wX z*2t0kvkSICl}vFbM94b;XFNbix(VJ1b44MD6$@9A!j5$-WtBW?Zjsy*+EFT~W|2kL zc<87|FJ_8h)?r*fOb8`R3l@Bnn%GyEx!Axc=VwR)Yen36`@D>=q98p1=2-fj!?{?s z&Aj@9AOQAx0*4}}<9h)eOApfKPS3s-ud4qfi8`BkicR9LnydPQoDQ@JT{c|$6S5az zY=}HP0qt(j*dZLkn*G77EsD<4mm1}GjJOPayWLT_wwE@#nlASz^7`kth32v{Cxy9{CaaG%hd!5SI9{I50-X^@*-NQBd3i~|}E z@fu&E>lbX!EFFY;9$t3vrYnlN|eLTyjpM_W( z6+sN%A4TlWI}A-C89=(DTYHl>vtvTZTnDkA(23ptj@~As(T`W3k~o+p z#2zHjrl-scnx51##8-6SawD8Dg<61z+iJql-PpLrH-Fo=u?=odvM~|xQWY^#Nr8^o zwYW-nBFin9iTV_WvtKiM=LN+%k?Chu+LH7X?2-fqV|c9W1Ib15WDBNxWXWWj+CE9j zCgyT*!q}EbPhy-Qfeaa|``kh!<@OTEhbNARaS9Ghgaj(ET%I(CecWb43#rTtjD+!q zH@5n<0}8>x){ix~YwhKs6QK&*s50^Y82e95lx2q^C^iFo`E++-yBJzBI1z)xmI@fP z5-NfJdOjY17eFdcVifwtp*8gsFp%peqsk>0@J`9RWHG6SeWM_syDA#iW)V!*?bbz~%DL2sp>yUTBuJz=$&FY_`^yO^MN|`88`hb}5 zf`D+%GMAAliMO!HAqJWaNre@nId9apb#@w5yxO7 zpqAm+BonzX7ACHLYRN@B=IDWJ!bv7YSD&l`s$oU~$8}o+KElZL)yEMZ;~Gv)5= zo6W`|Xm`qs$jv8sR}X0-q#A8lASD}92Mdch_~uR_vcZ9>RBBFlv+6r%+3_4pmN5h6 zLzi_hkz=p|frJini6syvDS01#PjifG^HRh3Dp~_l6Wb53xsZQt=A$4GmoIwsu59MoX0*T=UHSZB1d9i=4~QYrE7B0>`L>e}8BF*~u7N z3CDj%Xih>C5!HeT6an6{cshPe;z>h+AP!qL`}g_IADI+TBr{xK4JIiDD74N?G!S>VTD+IWst!{hx4%2B|-^cE?e-Qr;_=yqq7uGX+}6EY!wnGG_}4*=Jeu)%v7A~A443R#OI`xdZ6eRvM>JD- zD?w7yo6sCcuvSJeH8=VKcJ=H&&PvXPN>WR{C~IM<+#C~-qt5Y4WFpXnL$25utBm$; zptjfx!__JQhxnpGo3$QU#kzISO85hjmF!UL+PEH%(qP%NTfrY>G+kW=6)kpC@VQpk zl>CW0q{Ph3`<8L*76ZHlOdMw@SBw!MpkPM~pe^ID2xYlpo|+ z)7YamcfcTjtVVs&Y}iz6iH`9_ut-D1Hi4DB$P=y|h_1JY96W+v4-6+CD1cK8BY3x< z(Vj575BW{BYwhm<*AOO`if`?#vY2|^2{H&=58?{oAa9~O+bm}q(0B*UokZcCOIjoe zV%hl-s3JP4tTP}EsBSfF1emqQ!`3Yrlxo0EYgK0gG=e+POvD`17^|;5z4tOQ8f;wI zm9usxBFT$naxrKrb5t$|d-ps{+ zbk{%zOT?RXNZp!;VK4OU_3Lelju44BY!X8@5c33nydPEe^*T* z!h(Q@D~St?7mLO!*o6|2ben4kXp+{%!Nd^@5?Q!0$01~fiFxnFXe^PE9ai0A43l`< z!eAI1a}y8E#Qs4H^pT;8Ta)2vG~FfbhIujuV*|k$A$rZmM>B7*)q_z(3(r+6pD~3e zpqB}sg9=!jqcxhloZy8u>ac^w* zVgR2-a+gWoT{*`rr0OBnH>z0VndcZ6f3Gv#M-0q?7#h^}uJvv`sRn3#epU^Upjo5u zQg{|u)Oy6Q1Yiu~H@nd=5x0DI6G1DUIPC<0&5Lb|kSAS9i30x!1Z0H?_CW_`*r_EN zNaSHFjm=pz@JM@*^gLV7EjNS~_ufS3(V3BSHj0a~EE&!Wo_-Dhm2P^@ow~8u8SUSp z4Fqm82Fl;qEmzrYAVLQ88a?$dpU+LDyUXZ#+ zu;SIvU|EFodsJMpE+Yer5YbUeoDF6PnHMfQ^wd6KWy;bN?lX ze2Te4#B~KfV1r^5dGn`RlM>s8hBNq_vbu6wKO=;yLn3M&*3i_urN$Ur?7uU9WjNGC zznC>si4$jHs&DZgp7u~MF+?!JR=}nd4;n(I@h%eb#lWJgDJ^NPB{8+=@S3ZF(1Eay68zaWyO@(h9A})-m%z?Vry@vEr!Q_P`TQ6eBG`Bav zSAovMf8u^tbiY8JXSIYW09YA`XZvg|NzIZh1zJKf`%&-=D5euD2y|eg>54n7<43Gg z##Dr8gnP{#S*V(q*G%1#!d=2NNdPy4qs_^m-()k zUdiwfi4#ZakD8kepbvTKaYhF2?<^|6AmHd!9nO_EvsBR3}Ao-gjhxwgaTCWh$fnm-FympFqol<)TNwhZuh1T78|7(+nBob(xn+4nBm zvL1NGLcq9aJ1<!F_UZ-7eRKC7YkQpIj0VGC9}9+?FHWllkfIic-Q#1BrhqddH>j>lt6S^SE zB%G-c@Bmz2w}(h=m=YQxhePq@DCxA*>F=QD~)+-Nz_YR~KWhy!IDMn^|&#D$B16&n{s#inl zBe=IkZ-SMD4PhFDpa$UQk%lb^9BQ!a8c@0M4k3$g5&_z<&81#ce8OGMs4$R>#!_3n z-0Q%Cf(gp0r0yd{79h|>fufN@@|bLj{~9EY4B9w>4I7lmCPdyGWNB_F3?!KWfWt^! z_VWaEms(3A3h<4Vq~K`~KJu}QzGh;{*yw8o%GFea z=!*SLRy+4o`9>PzSL9~KSV{ueNpQtw#^4er8HyKttuYsysbhSi?3ah$dc@mk9!kCB zxGG<#;GqHsfru+=s{F$(4~q8;iOUR{tzmCSGkIg>QzUG*?^WsSa#m4ccGrd@DK=cb z(hjSBV#_)NmZiBNq#*5~AZW9x))05q8h;tS#Doxq>TNRatapHQGfMpqoO;C)WwJZK zV+Xqriv63tja!>yW`mnnRfbrUWsqGOVU+3W~6#-oFMv4)hxD)5$Yz=F~w zkuHd8-BHD0#lduCL4O?^>koJqf}_T>&wb6Hy`1)09Bu%6=T+@_9xsJ({3{+Ns>4|s z>^?Hc4As;f{K5tdNBQ(epUI?O$q_+9I7MDP2Q(yqh zcnHuvgSDY(Kh4P}qJ5b>ZjVLvC$7}+_2ZbmPh?yHxe98Px??%_EbQ5nJg$f;>n;fw zdLE6a>k{(fu_qE#!+>5gLTxaK z3;bV)jGcHJaz+FM1Zjb6>Rp)~@Um}0oOu;NZzQjx0qeUYT}`ZO82)3jJ3^Gk5n>|t za0wu{rYlRp%OSY{qGnDR%y|m`&Mg>P&DeG&fL~vcVDhQe1QMmS>b`K|P(3fZgN?(j z64P~iMdtQ^JAgfZ(l384*Eclc%VIcz&Ca}H5?_{s?@BI?8 zJDa;2C50I)i-?)M7|9m82^kEecguUQnnHf1C!IM|YoVy)6VH{u>qSxEA7y4`k8f2XHTN!u$-sIp!J7z4C^$MRU2YB$E|{j@ zn_Jh%>jCShTW4g^?=*`fmX zi_#?KM<2rlaIn+rb^C76yc|=~ZW=5K{CBG}rkz?M@cB*HIm0w|R&AA1{Far7zE#mM zhbhxrkXn_Vn${^CqN@S2f04*SBnZ&t`}Cd!9pI#bvo;?*AN8MDw^KVRrD;+lZ}ot) z;GrQD-DLl2Q$h|ety!Z^_oaR))^ zM5$Y=d(A#~an?z!?$kvNJf*P@KRB%IAd1r7U5!!tQz~ehd)!kb)ZjxY0i&r(-GvJa z`I@T-hYfB&5BZ4vgS{61`xZ2aO}Pn8ZyiYR?M@^Fp6c#oATxDJvGXXuI6>#Elb91Q=!xm={7VeqoU%_5<4o zJEVFvW@PP9vV}|BAC8tk_Z<91UksrV8Cr z*n{S6&8*ql&c<1GD)O>6E|h^aEl^_tFt(u&n@J7VqBS^FJYs!g)4U{xHxJjKzC*k> z#G<@mxT@^dd;UQQoM3P9o`Qqzbq>I2%j*iJjEx;66TRERb=1A@?YU!+y1Gv{VQ7jOK$mkTK=Y%-|v>U((?DT{MX&` zXVUTywfr~T^5@g?Pqq9@ZuxFnejoOMKa2cj=YKOTzo_M(cgwG&<uLEbCFO5wd360+e$MUxM%w>}TE5_x|9)D|uRrth##Mp*pZyQ`&tJFjPnZ+9 z!`~_XKZF01H8#I-`qYbQKbKFluvWXwUv?k7@$k4xrpRvOo87ulIz$1O7tjH* zDxAE4&r;Q{{geR~&f$Td!7u#8#&}Z8*I3E6pQLNpEogr~ntV&=@F_lL=D@xEKhl1_ ztNr}EJ5Dn#|AChOs$0I1mj77G*WL0{m!$&N`T5VXpjJE2Uv?eiwEd!%|F&D+P0Ke* z%J;SWuej|u)Arxe@<-hAe={xru9nC4`3GA51-HF(*M6+!zwDM@P5b}+&$6Iai|yZ{ zmdED5q2-~w%yYgihg+-tQ+&>y^Pi^k__p@LyOx~8sVAfY&*@z)kFDc}T7KDW@7$T6 zXnAa(?&TwopBNmhY5Ct~B?~7z>HMG7@-MpOy|nzcmdD2bww8zXQP!{Ja-4SjN7Md) zSW^BIEsw#`y+6l^$M5@^mUAx2`W@QnSuKyfO}Di?c0S)O8UI}^kInywCGCF_Du47F zr(eJpa!vONf~nOu-1VI@#0|^Wv^+NdXSMvd-S!TixUJ=X-7SAEJ-=^jd2D^}YIzKP zeyHWY<@V3T;oqG9Pqh4Ry5)b*lrP}Bdxhw!)qdYCCocZIw2zBgXUDB`${-t#@w}GD z?#L@z9-|-M)bbep{GOJ_aKMLJ&bfqO^wW~@?>ozewOXwIizVgHYk6$`uV{G;*S=ZO z{=I_s_ha54DUAQu_#_|MXFJR<~b_^z{`a|$bU&?|mFr~lSxq$Ae5uJxAi zmgnmI_9>~ifO@ZJy}ygknR+j$bNaTgNQYd<548S&8XEVXrsMut#|_~P_H(bo)ISWZ^Xut4 zAJKYW3)S05>+Nd2A|8U{eoO0}@nJ{K>-109BkR4Z^&a-?J&E(G8yI^4^?s!Fu7LSG zgMTNmfAx<}zkcQ$KXdw_dt_6H8_oy<3ZDhXJg2bMV_p28^u;q(erf?y1B6&I`-X?etx8LF6xJC`<%kV)zEm#({Mi*wO;PL*L6Ryrf2?q zg+4j+sR{Yk9*hAExuW ztmO-Cxxxj}x-vvtmEruFwzbeNXF^!Oo9#JgIKq z36)W?pU)|5{5SY~2LC7f&%6Cjy2lRykMJkf&ql?5_DlNtc7=Xq{aUYVzkj6Th4!20 zVHmwI?qm6a5GV2SN3@(cBH25Y;c=e33VUVe^v!~C*w1&hpR)D-K>K;wozJNQIY{>N zV=cdk_am9_m49^lkIuaQGvD~^>2rKRxbA!Z4R%ng#pw4nE&nZ6vT)_l*Uy%;zpdpL z-S&VviW(O1-FFmji|*um+J}IGorA;6e^@eyPqkb~CEMPSrQ9b>e)#OUmzNc`rucjY z|0nyvyW_|QyV{SSdpnLJ=YCDgV|)Ep!8~|Y?`wJAox>@^Y_a?!Ef)~7<2!QrGxxG# zc%5v2zm~`PzpUl4{<~TpgO%5`{BLj)c7E7HK7kznEiD(&wdD>i@V=JE?)XQc{{KL( zgwVie6%LB-=mO@kto6Q(&zbW+Wq^ir-H-<&d~eu?h5Lv6KFk%ZvCf-1&foFt9GW?E zoOgAcXYe`MGi6R${zENaam)A9_CL|`*qeW^Y-X(%JF_({f5h$Ik<&e^~5lt*FMU%)&bP}s@gA;9OW3ZIt?`rujy z+DF-1Ue|tNYk6DCLu=tUALuyO@i_yZh6WeS4C{TW^}ZUeC)5F9=sy0!Pi(x)3PWY% z4YXd_c(0d?_fEy}KCC$2rv>B5`v00)e+))1D{TFJRLkr)@xOByy4p|dTwl}j&^~h> zZxzggDZ)^FNFlK`DRA0+^ ze4z9A1?agl=V5s0|HslcpA^hv0sUCGe+Zv5{Wv)K5pE2A{to`n)Nye1^N?Ner_Ns% z#|=^({EC)`*30$0rDOalK4-=te5oEy&R_dkcE@q}qmQ)wakm_OyrTH)%mNF-_gv0@ zL5gd!_LsFhw$84W%W~{KII{BBv^)kEZ)tgm#+LPKd4_(__nqY*X?f@#v;53&;un5m z`***V{}wCR`8%}kWi5}yLD< z{}VPWvu9tXPW<$Ldq!cuCJF$ve||sgdqK-Xd$NG?C;1CMtN1@N&P(aJbhVH3tZ3oK z(W$;xGKaUcJO-cdYk3U5KhpBp{W`-9!_OD_%g)cy)!nb<@~ql&rR7+3RpIKN<8x*Y zc;??t_hF#@#OC?BmdDolwwA~4;rF$C(_P0Y!|3oVKQ0;ntaKd51Lw3nHvUyDkHO?r zVfOGd`F%P)F!DpTeWRqG_q3mWXuln~*@xOs=nio!&L~`z&F6j*me*>37i|*wP+bN4 zxvKsARexQSNuN#SqSK1wy`kg%t~;Jckc~~wd)m)01jaMgF6KUesQtv??Ncp}!P|X* zixY_RKo_+<#zQ@?<(Jusy*G{y{uM2kY1s0%xi8$;xA+S`H}U@&ez0|Tubg@o?#t?Z zQlUS>-#zls)@q^sXZf<0$M*HQmdEbNRLdWB*K{Yv6K`nw<8HY_ue_t>A-NBiXyN{U zz~|h){aHHBrzPXuCl?30Zg(DzP0vLwZ@A@-T>N=0kL|-NS{}j|{O(OH57E0Ue^1K= z9az|K=$;R?JakSAX#c5}Pw+W`EyF8{^q*ra$fFRy1CMBVY>XGQ{Mq~%BB|pTuW6mw zI^WXrzwP$n*qXer-5ck3zm~`F#APiH?E%|&wLJFzzNY2E zme_N2Y$4v#a#@Bgci!jswLCVzkF-2CzcYfsYPHz>?$`3z{4Q&GY<^uW57AI^{#yPg z?)fQ$!}7PZJVbx6{QZ*tKPo9dBY+pDd(SESe2TF$_{7|m9}}Yx?_Ae<|KOBYkMH0e za-Zg1nih=5^}M0wf}ZSoJ9feEl(he#r2Qu)<@Y>@N#G}TUdtur*GtN$CFO5uxg48a zzoU3V-TrT-@8Ug+EPy>Re+AaJtmU!wUDxth|I?EG-_Y_9 zUBvtGj+V#p*#{;4e^S!_JtD}6%fptnT%J$6KaOqNbuEv{-ltmrkh{MsTax>)<&>8u z`+v$9$r5JXQ~3Que9qt_(uMz)IY-v}Nb9{Ds`sCndJ8B!tMKqo{Ca}l49z!f zUst#)JC|3qUfH?4rS)RxvVbwaS2Azb`KY80VeWH6Jj7xC0WFW=geSE;gi|?(T`e!7 z17FuVF&KDT%O693$r&lUa}D1wm;=i{)^d6N>=~>4nB`~X!p7;Kb6OsQ;j1O(11*>9 zZO3=y!LOH$|8`0F_e;kAxMcjZ^5E2JvHdxxeq!&>2U;%Z z-@=*WH};8^hv-Yr<35FxvUyxwLuLH@GJn}|9Q%vswftAya>wrA6)lhL*PB|t<+fM9 z9m3OlS{{S954AjYUY}}t3?A>hz=7lNa8b)+{Xeheq5c=p?<-pV2OPxiAK#p<^lko5 zg*xwRov-@+=w2`2`#;w@Z~ArqB&GY#KE%Sf9_XBw-(V#>-&5Pt!RPVSRW1KHmg9$K z^n!jDq6^sO>stOPdXIYLPj`QdGojbQr^}E>I z?xS)KKei3~S=8_Bd>8QDW&N(`9Cx+O6!nui^Q;{^q1Uxe2%dQ_-%)sd37>QL!QqcS z(0+c+9ZPL1xWAuhd2E00xyXjKTI`&cwcPFt`+QQri|ysEmfL+}n^*L^*gW3U^4K}Q zr{(TB|3JTU=k}3)7n|D|5p-tH`Ck3bo$opQE{3nJYI*E^A82{(Twd4md${=)t{s2j zx3&Cnw;V8J^|;^H^1tSmJM`@U83MoAsX7BYbA+sV(*?M|Sq3k}*H0uu(SVqSmW2=5e-J&$nUxZHdB5hMr1`H?{m(x7^4a6WRIqv`*;F zxDV}qq~$Rhs`eN=uhnAZ3tIlOpFt%%$J3`osmJ~w(efB9zfe%VfcD>1SR{L%ffd!G zu+G~R>inRj4(Ix@&gF~voUFx>qo2LRg1D~ZoR-JhU)Ay$ejjN0U*RBjFO677=$_ZL zJjQ>$t>u^9_KrUB`&#}5w_Npvvi_3xXQkt~AKbFS(jofKoE7i2!^d7P>BqwT05IkE zb9!4qOK7$?wIBB_|87Cwq|bh!<)7sq;OBn)|FO=yY`n8gX_C-;+_MG!F0`i{?-4C` z$9rDktZckj0^@zFWW4Ws<8hAf>vytr3s(+Yd{odU+n;$Hzwq-Uf7$kq@5}vK9)s)4 z1?Aj-3-{l{=QH>}8G~^1U#58eb?xU1ZXHL@{f@$Kj{Y?`QEoEN3ormfv+0S+D=U?J;uAl!Z?Psd}gwB_6_=c8$7N7aUzQ1exF4@Z;XxrFc z{#eUnd-?e<%aBps-(o>I=lQI{R@q+O)_&gLaLHc&v1}6i`HuEewwK@2eqww1BQ1CL z@>AP)$zI-fg_En*VtaW}%VT@_yq3q{@|A*e?tz8-vb}s?`}rrFY_gYcBzyU>!hhLb zp1sNr!uOtVc}~miUh?ifqThwy2CiXO;q7bqdc{cyY=YP~-T zji)>X>(vx4%IZC!_5Pz!fB#{6r=JuciR({xwfy%vc5+50SQ+Q@Egk3U_?+7(wJBdf z*}Gbg-DT=I`0@iC>oV#jV>$G|CtCgmx7>MWE!^*a#v8-f&bCRR@$4^NV+ZjyKdzpmwd zR!Yt~^~alPc?>VSQPTfACH;R;(EkFa^of>lyYu6oJF=pCH&__g_pWJqh6ZtX`xg|( z{t$iS&eqXUe^cwd8>;8%sK2ZAh~qN-DgDNM|Gv)YB0eYkj&*Tbgd+?0|LZBQ4+Ga9 zkk4m7_xv6^h@bDWmdDm^;r>^Bc*R^!{{o@a$hlw9egwP|I59yyIFC0=#(7`i`HxXI zvnM>uzc0fW{zvQmi%`A)!qi(p**yvu|G8gJ_6NKWzF*wLFZ>k2&ULNx^Q>ss<=Dqe zwfvl0uJY>zeD_9$G2Sg1wU-deqXdKT`B>TzGr zi6A;|7kO37LvYLX11*oO_w|zg-!AB%>-a$7`4xQ5>^s-%&?Xk{|14Bbc?8b)zUS}@ zKQXwysO1AzvT)+upXasQ!Y%vU*Y9F5`YkQDFv>P>>36Ytyszc4`}2{O+j$V~f8u?| zan6!S!%u8(=d|3;jr~00eaC*T>vx}JXLes6P2qm3<)QnvfF^Hfxu7}Qo@Z!8LPFDg zPhtPxLH*oWt1T;G;?K3-{}`(G-=%lp^9oxzA10wMPyZsRHukqxp&s|(Sz&tOwp6#Z zJal*2{@Ysq*YP>oLr1Uqu9nB>iXUqE-*DUiL3##1DH;FX=h-lR*VnW>)Iay>1%|PA^!Ht@chRS*PoEcpnqz*Tb^ZjO&*1-L-v~S3OxOO2&iz;1I!gPopZgU4 zUhv04Kc}Bb>Gz8i?BXZX56|#zJpoSlbx zl-S4T+W3VZ`IGcvk_B*27Zqk+!skpMM(2^}o;I`}`$jIHzJ+^EBj488r+w3F$1&fk zIOh9aTaNi7ZCf)m0}VDHutiKT6GO_-W# zyER?fAKmJqM-FN_^KxyYoxzQvZz<;PFVf3`g6O(ytBIE)_Lf3E~k@+?nCZFW3 z{&crB60{=ezyq_GwTJv3%-BPHc>+M19Bfaf{V7sx@or9-3Dt)iXH#_EBZE<^oLFoJ z>MI=G*%BGv8#}V1dM;-yVDTExX7whLaknJX)C39jeC%GiyXwc2pNgcf&2FI?H*>-K z+v!({&LHh2I#4~DVR*Ye=|y`kX%>aI+-QwOW|(dvCEsM4W*~2FAO(3kd%Qu+j+{J} zW&@U1y}acuyqL(YhtzU-vhSyYLa;u&NN#ye{42O zV+T9P=Ypm_ICoN=YJnXjzk~*-}#^tri zJ;N8Iem<9k*UTxitvdHr)*bY2_d$EucTXTEc`5VQ&dxR0Hrb#`BSjCWp6fVpjk8ZR zrtITnv%uwHd%9~ggD&puV>8?R=>&=9_VCC|`-i>tF0o>LwL3c49`suK<6fsf0cneL z)i;2Bw^6&<-2}-PSk$q4CvKPCH@ipfy~nvXRzOVm_PRYlM!_O_n=krUpu+qsjF2v* zmm5L1zP>sjQPrA^k&{s9YY>_B<<4%ea}#iV*c-QR2svi&gE_r;>u#`h;E3wEbfw5x zI5QK`aJ6SwsI;#IBG1lkx3nCF~Ps?w)bxI1e+pPXLBRR znnt4y(s$hMOmRBnej6Ba(gGt8pH2>dV?E?Ak9}ACF6v8}vHQ1`3{KAY(r7g9;vVD= zQA$=edDd*y5^^eoC6*o=-Ik`g#^*OigF81yduFY6uq*cKdIQhHwS%Dy!36CInU+*p zZ4xhMNQR_r`O$H&?X)7F%qb+}tVl}Pm9O@@5JtGYn}XFRd;J@`*}hH5`Aeh0=wO_k zk~VtmU}vW{&UCl@H6)m?FFrbGkB2g3sPu{6RCgm^dS06Lx-7|T?V3%28-SLyEDr}s z8O|lzC(5=UtI7;`lr+4_hS!%i1_w9#dr!6Z@D`2ht2o|FR^QxQB6p^K!EkI7(rKM> zUpU&p7DSpi7J*=Zqad%E;Pz`@K=gqwDCruEZV;o5$D=X!BtQruP4zI`c=fQ?nT~{) zM=EP@{`n!croERiwwq46-fH#shzVN#o%LrYW3U-Wo;?v^*!uNW6X~Yq&1!BpS53Bd z&T4xdgrqN-!&f3Wz@O&UC7*%=iPzEu#g5>C40zSd>-8nuL5mrV*O5p5>h@x2ose)H zcd-2C6?B@UZN`>Bl!w=(Gp$di+$3MB!p+Go%DVtC>Hk2TLFAgLH$I?hbNrsK|1&ZV=(mXo<(-?(PbR*v0nHV-$i zx3*UNORQKfKbgf25|a0XnleX7Nk;~qo2IEaB!AMlwCw{()_I)CtI>=SXIR9bk4v_Z z)CFz?NziOw*gu%;VlJJVT(>K82@ip(Y-HpZ;cCGf5}GnpEz^3#t_1|*4l(IEhQPii zhd_K{>p1JhWOA+9(%Vj`7!=>@8P;9Wk+&gFI0h? z&?!3iX_m-CpKZA{=>W@jdpqre0f}v}sGONk;zat=S#_I~AkJ@6-O!x69$XbqsXyl_ z^+Qwgh1hve&+!zH?2*bc@GT$#pypE>0O}}X0#Sltip+sE+LLu0!RD3gEguGE=>l7J z+%8DW1^U>U?)BoAVjJ-0+>6|mnDI(McpXrbSoE-Z>2MP?4^at`9B`PwW$7V$bpt09 zt(!&cq!KbuOthVO02`>EJlD~>%M+-{t51Jry9YL-di^Dc_HwmBa^KiHXmxJi9^gH* z8AjO_E=rz zi5qA&5}jjbASee9jQ3E)&3rJwItX>y8x;h zvsiZU8TQLQnF(qNKRBV9k+&vP)!#NH>++0Sb$&O>h|Qtzm39}j8&D0Af95Ra&^gaJ z3=9$e(QaO5A_eRwP-O}T%dM;6N}ao4n360P>T!n&2TRJyu%h1B-lJ2U)hg!s(r&9h zi}M<}f@; z@eB)u8D$exCcN7GQ28j+D-djyO-~v8YSTmI@bo}JWcdnvVXMnJ(hlPIl0~^g90lH02@TX z%Irt%bpZMzFPTYu70%adQgY;8?b&gs?EvfJVKrih<;Vh-TZY3{`>%B{&)N%w|4{sZ zzdqD=Ad8*HaVa%!Ct>$_DWU0F?StDHjcGvgLXr)mP)dhSS@tM<sy|!1vmha|B+45NW$LZ8Tb~gFTw#!!i-#FPf>qp0&O1YKlYazGAyi*_wvPs<;_= zlCUY<7s}>akV|bnY7Q6YlG!B76WQMM6xKTJ{dPxv1U!N`(xkD7gHtJyF$m&H%GY5J zkaJ#a4KdqC{Rgr1ZW3m?Jv+GRDElgahp09kyAk1SrI{e4N7&o*+-9@8m$?DgvPapI z99*W>**|Z-xHzfhMu7y=ig@NByxeMy#h{A9%S1W}iFw!Ps8j57{K3w{cWcnwq4Xj$ zmWR5M`H-B>$a2v^Miz-%N3nzBlta8)Uy-vCA+jt7;2Zo^7f%g<Pmbpz7 zrhy;}%Vyh#t1OX#JtDA{i7YX-Uj3cIg$#tL}gQ|<2d&Zrs;#BOE3>|hO$Cu zz7*S;C~g%*O~4r-c41*R09F%;ck;OUTr;1ru%Q-)d8*Zc>GZT`=7rlp)ReuKU_%rN zvL;TIEu2DDAXsCTGYgL~yBSrUl3J#Vy1OK9UZMm(?zlpTt>!i@E@aNoc|L3dCc_g7 zY<5JHIp^Juj6xchR%<7>-I0OA`>g<)lS$a*r3)LTS%rfFPU*ci>7ao0>ZTru$s z%*?k7TVQyrVajkb3(h&*TgjARy2dH{#%ks;-6{9Yl*1LvrVPKj;FSH|oO_#t!JKj2 zOgFT=J6=WF+U2j}QYFk+K7!o2m@#t3t2YYv^-Q$@Z>+a4TP^R-Vyfju#u0&TzPgbZ zSFWxC<4FD7D`ur0R*spxalD>^&B57elK@a;-YHwn$Y`?Li`)156C_S2as z{b9MhCs+x7aGD`YJY&FDU+MPg*VWtW^lXHgtqZM?M~z3q_=iuDFA+!PXpkjH(X&F| zAzXLi1_V;fgam>B*cHerOc}Y}atn8U6BgHTNGOuhpN9=Pjo@H`W2EyzSw)Zqva1Yk zEkGQgn&hyYd~s%EhqR!8=R!vOaYK~W1VhS$DE5V!>-eSA25D`LTq_Oe9r)^ zF1yDT;;U^|0MbI6Wjp2l$DQF)gM#rOm}VM_CPmvO%p%OyZo?v$8ZN-3aEBH}Isyd` z3h}Z8p25QU9>Dq{VuDx0ayHbP37|C5rQUX$yh0;~S^E1%9oKP%3U&HVS%fzl=jd$W z->iTrquP|a;qcsEUE#ZP(=OPq>`)293z!qkVd**UK9!Lf20t(FD%kN^<(ji?d?Hh> zy#2|1nsN%XsEoY5bsxx`Q-IRU*snC5!^rg&Ka6A+fRv1w9>lLFrWbO!^h`w3YcFbi z+^YVut9b51-UY|+S>!aXC2_!X0PZ_1q za5Tw!+WY63ou2Van6q#-Z1g*alcN6H7^AkL(p4Ul5j$sY(Hur62|Kv4F%%%?70qyd?DrsU~7Q-7!ST&)wJ(UceByr*@2yInjVdwQ$CPLFWwHah_W4|9CMoxr+A%NWTZW?=*vC= z@h-x;2LyD>$q2)K4YP4H#~#hw>lL4YufPz6=g_FW;)JWUw`(4|8`FKv1f=1mg$^?| z++E$@*d%frj0?1Uu-6{nY1vSbFdW{R9FmarUuh%%yU4-hxfqu)%Y`S_Mb1{w2@$Xgp+aH7`q_g*wnoG2pBMa~pn z2>_H6L)fV#q1>%*UM(3Y{g)6q^;rhPaCJUsG0n@07rGWB1Sbs}Y_Ywz&=iE?eq|^Y zg<2IT?uVX(xqyP>5?_vPb8lBAh1^{F^$=)~7$}k0Su9>*6@n?x`@$Ks;i<-qJ{Az; zz=ov2$0Dn)o7;`bX!lO?HhBXb=_dJo=q(B$HfM98UM$^Qr#j`a1@(bht+K*AZuSbt zq0`pSJzPGV)#0n*NQP}Y0U}>2C%mqsgJ5hYst8-EjL3+{qw@6vM~XE_&|AUCALT1u zOLc4;SAdtQ?~x;i%qh~a zs2c4mgk4ylmkLT~0kVo>F&_v@Lv0NFQ0A-gx|Vhb+MtTYYqnV^?55gdYGJUs4F02>@4&7rSAYw10 zch)|H%QW4yw(Y9zmrnyl_RFrNQ1ONXn&qE7&chqqU@hHsIfC%Kcpc%3frcNP4 z2p#_hq`s6EFf2#{yh2(mlOG2J)HeBfVaqnJATyUYuVCAZFt=$`5nj94w#^8Wq1_|y zw2LgWp^CU1bVV{~J30RDdlKD3VRan4IwD9zuV(f%-VP`13UZxpni1;G$J>@o%9^NG zHy<}xKgMZid#x%Q%-?wT6*=~dGjGt*_ai2ElV|YA8xrnyUON)*9h8wg%Nd|E>~Bs2 zxY9w&fxL}MsCKs*sk}AO^m^+X2voYcH4*b44*?xt-cetg><-{SgII%%j@s;QbT*?h zq4OF|Je6rhr9vVt@+DS{3%L$3^z>l7CxcV5ViE@d-}+plh3Mmn*zzzkr+(`Z>2M%s z^ej@kXljnevTkMPU<_+gCo`2f5`XJwlnsJRhb-R}Fyd_Z4Cb6s3_ePVEX0s?aG zYy;3(9V36>XxM6ZI&c$C+~ARp_C^!#xu#7bz!y0`i6%si5%R4ZFf9X29?%$SRuXT! z%~JV89=frSF($XFAyBcciaQbO>gbChUBL8!JKNleECqQv7}S6sHol-)x%NUE9Cu$f%68xla z;plU-mwuZt!!e5xh4T8E>5=e|bjgRsq`a3Ts>qu0BBTf#>Yfx6yv)E`d-PBQLCxWu zy@9NfT9gbI2pieRhJFw3uoz^pMeXOI*G5 zHkab)e9w+=YJ#fWHMo<_qibJQo0V@xdpn=urlcMKxLOs@;wQOO|B7EBy&kKQVsV@is%o| zNoju;>nzIfW~0pr?Ohf=2W=ur#py}?gha|)lQsPb<1NDBAH&Kvu(z&zgbL`%Q1X+MNuX&HqZBN_O zb3Hg7J=pr%^=IOOjq0y;4vX73Lf&B4@8)0yD~r-N{z4SOy=4^iTz$_1

g+8c;(dagy(Rdc?1pmh6W8o5A>w@!n!P1N+K}A)w_qhP@?3hLPO+Bnx{>h+Ir^?~^0!Eg^CV$w!dv(0-QE%+-WAU6Eg|AvdEDL-BHk6j z?JdE-Qa8$PB9FhB_qYHtY?JXhV zT@keYralhGe_wQ2hR%-&{BweT1c4b%l>8U*s-0}>)n2EW_~Ciqvl z-1p_aI|-2z@_6rxlJ=J1U+EF$-W3?_Eg|Av8PVPnA}^5KyAq+jB}BX{1ln6dWHrgX zE9%wXy80L1iCu+f|G(*v!##3;AoniuAFr>q8T?0m`O?@`^7jABT>tU<+LZg#NaO`S zKPDLY_qX|ZD=R<7FVVcZp}KCSpQl)lzuM2+TKO}6e!P`$_4D>tzQ@lySb0QuCLg0x|QoIwDh#{e|>K+D?iTvORnBl zuCG*Zj+N`b5FcRW_xsP2Y32Ga2M1dD5&mxm4z_armn>OUuK#l3d@Fy(f1V4hT>nO> z`RQDdi2lvV;nw3L{!h5%Vw8b@P4e?GfkfZczbQA?%DeiHzuL^c%qf-pFHMT`Gx*>j@MiHVm~)73acJ6*f&x|)%kJm@|JS*SrKmUzZe!6#I&d4oRKF-f)Sos}(ew&p)<>xc4e7&E~vhqLt z{0=M6YT`w+t$duH-)ZIR{rp}lPxLQq`hb;p^z(&QKFH6Dt$d=NKW^oV{d|d)m;3pX zR{oQpmsok5re0KPi`H2AOh13!%3tvFax4GH&)=}} zKK|uj*ID@!e!juV*ZBE6R=(NKH(L2FKmWkW&pFhKKD6>eKR2%iABk-6^DWlncl-IL zR(_;^S=t>|ez~9jXyp_9e7BXC`uVR`{EYhRYvI*-jFq3^=dG-KxSzMN@_YQet(6!1d1ovC!Ou^#@@D=E z_?}jt>gQ)!d8VJAW94`IdA60m=I8oVs5kQ1w$slqvmSr$k=`SsR{nyY%ZJv*of7Q?B!$|`9 zSAH%Z+7ZZ4_Fsa_hY1Ao^ZfjJs}I-u`6Mg9+s~(1d6l2%S$UnG-)QCM_%HouSb4Ue z-)iME{rp}lf7;LQxAJN~Utr~jc^5d2JZR-veqLnd1%AHB%HQzw$E|#~pD(rYQ~hsg zp0@HE{rovA-{9vjTlpV;{)&~K<$r6m*2>5E`35V0*w5d#@=bpJj+O87^Nm*C)c@9N zi^S`Y8UqAoH%1>_X&2Iz$yEE@zY#Zh0jjX)T&zoBL z3x0l%l{Y!gd&d4&ev+RLu<}d&e4>?a_w(zl{Gt@^`E#xOX+OW-%D?gR8?F4vHtK02 zw_EvmKc8*ocl-I>R$l7obFI8#TkrYrxAGJHe1VmZ_45a;{1HE2Xyu#z{6Q=4dA#R+ z%*vni^CztQOFu8M@)O&6&-1L6-{a>mTKUg@US{R(+I!FQij`mC=WDEdiJz~v@{j!d zbt`Yy!F&F~7FC}2+IsxGe*T@6CwKB5|C5#H`uWdR{#W>M z6Cy7sdbj45px#+ToBH`Fiq-S@Z?0JXrmin)WnPdFIe_GiNq!*7VfpI$|Bt%&0I;hn z9{(Q+(nWf2yFe&X_HE0CPLc)Igd}7`2On>DUy>KLvF~k2C<0PNqzM8F3P=YP5mb<( zG^r|8dJzSYDk4}YznM8_=FPq5&MUhczyJUH{rrag+_`h+%<1*gAT@Xg)@K8TV0?-O zdBL;sDH@z5a2ix4a2oU^a2l*6a2iY`a2f<8aO%7#aOx~4aO$)saOylJaO(6WaO!*| zaOwmlaO$KaaOy-PaBBP$I5o}*oEpglPK{dvr$#A(ZxS#Buug68dV^DC96W>d>wqB` zpQ1`Jcs4#om0SX+N-Kd=C6vIavPs}nNhENpBog>G0Yfl8wXMOoGx+ufZ!mb;;Ee`v zGI+DWTMXW6@QDU*Gx#Kf?_ls94Zf4XcQ*Jg2H(}-yBU0UgHJa26oXGSc)P*(F!-JZ z-^<_~2LFn|rx|>@!S^=!41>=!_$-6(WANDq?=<)vgYRqb{S3ap!4EL_fd)Uw;0GK0 z5Q86T@UI#?WAMWao;7%v!MhFKWAL28=Nf#T!RH%1Z}0^MKiuHG2JbU?zrhC#K4|bG z3_fJ=g29UhA2#?xgCA+|MFwAN@S_ZVw84)t_^}56n!%4V`0)lm!Qfvv_=yHT$>1j& z{1k(qYVgwx{tbhlZt!m!{0xJC%iw1k{49f?ZSZppey+j4ZSeC9e!juKWAF!r;F&_^k%N&EUT>`0WP2!{B!s{4Rt4 z+Tg!2_}vD-$KdxG{62%zi9B64F0mgUorTr2LF@6Uo-fh4gME{zi#k1 z4E|SxziIHl8T>7Szise$4F0ac-!u682LHRkKQQ<|4E~|P|7q}#4F0jf|7Gxh8~i^8 z|F6M6G5Dtj|IFZ@8$5ZUALjp;N_qk2{|!Fg;NdqCm-&&aeNI!Pq+`q$%p%J9ADee z6YkG(^6MJ%>lr-U&*Suj`*|GS(9q*QW{yJY2j|fY`ArNS?iWIJ@cnT^ep7>QX7J4o zKEdEy7<@~EZ)NbU4gO_=hx?$MAGS5*w=?+m25&HU+Td>YzDip9&+(}yL%!MIEd~$w zce(gZH00Y1KFQ$WJ~5|%M?-!mgYRtcT?`)XLv!KoX2|bu@W}?BV(_U35BI-0d-gEo z_cZuk2JbNVR}4PQ;L{Dhx4~x^e5S!?8GIju&o+3c!RHu!UxV*w@cj*bfWZ$m_(29g z*x-j4Jlyx_^3PWd`HaC2GkDhET?P;LRXTfm4Ebu)xUbUb$s6(u41T!5 zdkr4$!*t>H8}b7N5BF_4Jx3Vw;l52LUohm01|K%~LW3V^@I?k+Z1AHDezd`lG5E0t z|C+(WeW%WE#~bn|82sx7KhfYP8T@2}pJMP+4St%zzhUsx4gO7opJDKC8T?FxpJni~ z4StTn&o%hB4St@%&o}sY41R&ZFEsc?2LG82nCy-(~P$8~is0zuVyV82ny?-)Hdq4gOn$KVa|&4gQe9 zA2#?S27lDxzccvn4gLp%KW6a94gQ3|pEUSW27lV%e>C_r27lJz&l&uAgTG+#7Y+WB z!CyA`D+Yhn;D0jsYX<+b!T)0L*A4!L!T)OTHx2$bgTH0)w+;S|!QVCbdj@~s;D0yx z2L}I#!9O(kKMnqo!9ONl$!P5qBGYhEQ9Z3@Yx3MH255Y?`!b=48Fg?4>0(F20zH)2OInlgCA<}uNpjK@WTwAHF%f7 zyA9rB@SMTt8hoC?=Nmk4@C61x+~B`8iQYJ@aqhIy}@rV_>T1*={1t=0YVbc9{56CB+2DUM`0ECL!{C24_?rg*o59~Q z_}d15$KdZ8{5^xeZ}7hx`~!pk!{8qp{GSH@$lxCv{9gwDx558o@c$b86N7(h@XrkX zxxry7KH&%R{{|mt@bLy;+TdR>_%a4x*5Jz-e0hVfVDJ?U?ryz~yJ&psi-!El2LF=5 zS26gi24BtKs~da`gRg1uwG6(t!PhbPx&~j*;OiTF1A}j9@Qn< ze0|T?*aqXfjqp0pn~85Ld|S^C0-hA#EXi*#@(o`8>%<#`^Sjp(PYYke%RffEQTUdg zzYd(=^@#rYFUdEH{C57~=3sDrswLnviMI-0(aZM}pBV6O5qG!QqbSSYKzx$Of6?oC znD`FD*Y*58;yVU>4KTPqwUcnRe;eXE3x{aZZ&%<+ewb;r zLK^jl@)_cLi~I_H2f%lLui|ac|2$&wrw#tLp?}jxv}dM-%ldJYkJNf+W@72fH?9RgmLx?Ako z#Pe^E{97Wwrsq!@dfp~}n8+XI<(Fg-_{&(R}+~~K$B#hUfaF*YQ zxcjOL3a;(MQ!T^`BEOsG(|{+H$9+hCSmePB`V9iFOWhfy@0o`DkBA>BdN_R_A--5R zr{mkij~349viuGh-;hrrevHU-eD@-LtZ>ffUnl-G;g|V%{SbJPAMOHPm-@NHm)o_M z4LzwH(az&VKi88D!0S>s2YO~2^2ZVXy69p5{E+xb!nyvr2Y8bGPaEd^B%zKQaADIsl&Yfq9Ol7;^&JVw)1h~7YN_L>se}73^(Kr z#4i$guCI;&p5(Wm8uA|y|DNdK{Lr);h8yxC@k>OW?Z1Wi4}`OSUI$*6a$f~X!H@I* zTDznEP<~J1mx&(Mzlit`1AZ0pD}>L&K;ZW{@vDS$yq2Df;a(%0>%A=u{uScaiTp-R zed-K@|Bm<#BF}#K!W8twk0qb5A9e&@p9!W}t*?EE?e-80mMGwFGW8$|7 zU(MTdFY#Xq=X&oM;sy05xtDz#c_6X86MQSUkb{RQv;H1MSKo#^Fx1&?>Y z&jDVa`nTv`*V{8p{J+BY^85zkp9*LBmx%vIIJfVg07v^*@%Hh_u600RUFzIryxJ7! z&ouBP`==WGK;TLGhdqzS_gvuhso#s8-|+_APkh|cY){VrM;&y?>rT9~{=Vm@`*Q!h zq5nPL^{Ms54_kUY_4_#c<9c@Y{3stF&o3PYd=>w${-+4MKJ|o@yP|)1rXhd1A%D9e ze~-amAUzvMytrJfK0DdYMuX2V_&kFb41OAL%n#3ORiTEbMx&E939PM0d8z(qz4fpTKz?0JVLW5s#@VgEEgu!1n z_?rg*(BR|dB-_6ta9FnzKkVewrGfYa;Xc_?`x4(m_~zc9M-ks%_^O`Y1w6@bFOmGV zA`i_U{p$Bcd$tnJ;kFb1vTzty)9)hSN&2rg_{|1?+~DsSeEfdN;cj8@T@0Q9UY~kO z>Icrxy~G>zeBpHDoLe~9>tqURuQ&l(4!o?S%G zYM$qa?<73$`6I+%7Cjtp3n;8l?JDxj^Tb2>$BBpQEStgrwmvmQ^sqfg6W?7p+w&&z z*Tf#^meB8WgRglA>YpllxSY-*-XWarKb812;q_kst;F{dzNY7I5Z^;M%WrZhhT9;V z^VJT-rwi}$diEneLpXF7>31FRH-h-yZ}2}6e^caH|9=g>##hnKaNQw8{B6<0{<)6$ zzG5d7ANu{5_jLy_ILFo6+Jxu8ka?T!f{zM@o=1SCh>03!}ZcQNVxix z`zktG$oZ#-cvj@OUb>HXI6iub_$$Qh#x7O^~@u_SUBrBj`-2SS)!C=$OyIP1TJ_@%;k^m=|n{QJUp@ca$pR|>zt^H~cp z+^dB*d;SgL*9zam^LL0}FP!a}emLs+k#LspC;k)RX|LzU#D6M$1J6Gqev@$a^De!p z|7XIt^zug#Zxp_Q=jRh|63+SRKH|R!_!EZwc&MoBQ@4sd`=^C?*pJ$u_^(8Mb8pWe z@jHaGoi`H?`#-M|zf!cX(zZa9GQcMIom=MxY6ITsVZN8~x& z6$Vkyy#YUx_xafxNb+A5dDinZ@r-cJ|LwyV?kfR5n|LVyIq^SxZpQ#c=l&zLD48O?;|w_UEz0JA`lT z<^M`N>|ZrOM+o+{iaguXO?;Ygw&!l*vxKuf-mAFqyGJcbN}ID;$i>lZ^RE0dDh?dP1JK>z`Kbb5b#@xKPLI7)!Vc28K~!A zk^jW=bBP}+{FHI-!TZEB!r7koZ=s&Ugm3BfEF#_|oaJ93-YuNvS3eW=~XM1+|HtIP>IM+Yd5dWHR*1ytuC?EDS43h@T*w^-nq<^}H*7PL-{KX>Ac79Cq-w5nn^8&Op?8i0%uS=aG zdN|w}B>yeZvz52!V&Z2D-@)_OiJvLF#q-HvSY7ImqJI_7JAm_ldqn@t1YV!IQ1o2n zAD%`$>{s7P`p*;n@F)HLO7h_3a-FB5sr=PwWs`{%2D7wx%R^!;3TOE@iQg3Pl`lp+!~XnK z;x~)@dS3tj#D6ZF{eJ@Sa2#m?~pX~Yh#P1Z&_B=p5>{qY)eYEE;k>`Htw~7BoIP3X{_`Sl}Z-YNTJ$DEE zE#mhJPkTEzx)kLf5YGC)LHxmh-$MK$;T-P2i9aHo^>2L{>i?Z^j#rU**iXKQ_+ui^ z_WYdq+xpA*jE z=7~QqoWs3_c-W79fcT3d&*7%7K>aTX=Wq`sezdcQqQJnW}Ux(>sA zSL8Wgok#rd!a3jmm3Y`6n|?j&`G?4}o@%W&EG1z5IV{ z{u9(6$}c4T9ntekFaI3yy3|pk2Z{szCf$g7Qo^_L{3hbd1-$jAC_hg4JTHGD@fC!h z?fGlK>r#&iZ}WWeO{nL)Vkf72m%+bIJnSD{O8gSh!|8q}@s%Z9PWM*~`Ok>2BJxFV z=l(xKJH!6r6~tE)`IWu=o5a@?&h~6^b8A=aUtGj(XM>&iUkc;u{A%^$V0=S2*XB4&rsf zIiFk!ye{>yaLy+wFswecxp2-WTN4lalRFa+`;+sCPY^xaZ@G;4mclu`o+rMw@HKq8 zeDT)gbesUZKJ{gh-^0rvPkdY98+!g4@$CcNejDmZ3!m%dFC+d3NiX)p{RV%Fc-Sx6 z>{qD2N%XUxeTj$tqEm>6{ha%VHwSt?B_8&3T5iX1TSR^{AFtDiPZG}gXLiMI=9`74O;A)Mtu0KQ5p z{Eh!jGGEK!oxoxKS@gGgl_wJK5dJ04e@gr-!jJKM+})@rY|7Q7} z?n6B*EwjDX!!KS=dpM7-Xt|MLevBk0*YJ=;!gs?}$$n-sSE2tHH-Tis61${8C4wSI@;hV{Ta;7Rq;B7>i0@H-6tyun{L_zJ&Iwr73d zN#$ie@h*ukw-+}P?+*B~e?UDw!W(^hZAyG@z;`D;Kj4QFUm$#IujeA-y}~#5{Ex)@ zg|qzXkD)z-!q@Zi3y2>fd~MI~AwDF0ThG^f9QCZXtp78`_0Q47HxPcP7kJ6bvmBSx zJ)b~58!XFm%x?l-ms%*{uHyB4@k!*r6VC0?zQEx;j)cqM+(vv8;T%rgQ%;`cINURd zZxYz^De$_~F%mA@bI8-kpA^paTtoah;p=$&?*U$)`nvF`p1(}|B;gZ0|1a@+v42(1 z*Z(8x*-SXMBRdff^&bGdF7=}5XL|}Hf0}T%=Pcr<3uk+-Cq6;KWqTebzNPSq-p;p) zhx(U$2JLx8^s_yi0k2P;DSV;Vvpey#g|j_hCBC(U%k~^cd>i3h?_Fl-zY};}>MhZ~ zjt}>b#9tHM=J_(uqMh4`em=pz1Mvpodwcm|;*G*vJin26lkn9%e}{N;z_)rXxxV@q zaOj_l{OMlL6T~M9KiBiso=5rbNW6M|y*-)ucZE;z@E;|$7RXC^1 zBI3IX=XCiQ@yWtDUEU`?CE(kA9VgFxC^3%m0 z_Ww)7X9#EiulFj3J4-nGe?Q{;2xtGFM|^g`A0yr=oc+JfpHTn4!Y@j>-vPw068qWz z-ynXS@Cjc2Hsbq>p5J)B@@uI7K;i7~uXxUXv%+r@zlQ%5|Nn;gb%FmsCLY?k<)6|2 z?};96k6MBAe|r<@pAM4$Ado+f_&)>w6XO30_>08r+RF9`?hd#0$bF_!q~$k?e<^4Sp8zy3`j%4~Kgf@l^u;8gPy~ z+lv2wM)D6W!)$;59|!(5S^h-eb*V>1p5yf}@jnPZ*z4K)O_YB^_+FkbB>uGU@tz+G zJju=ece{bMP_I!)v{}RaGPW-RJ zxAA)3CjO4_H9h~rTWHU_!dLKob>e>)-spJ;@ehTw{>8*U7QVHYznb`egs<=U{lJsr z^)$(UD)Jk6`Hu|wmEK1CQ;wuT?#`9kQ zPqP0VlK+y(Z{p=weJ5FdbA#`Ue4Kw-{qq$=zRTbPz+s=Z*u#E!fcT-p5AtD5dN*1A zT;gkpJnOlIcvd*;dC!nv?LE{V-kY%-@Faisk^DNMe}cF3d&IkiKj`@i@1y=)z>fu< zr2hsan+_gWza2E^baQ7g7v~Ui09`R#K-0Odm_;JEn|9^;|Ae{AY{SOTHMB%J| zI`CC|T=YNRCi#O!p7n3=A?i6f;Df|N`F|4+^Yem#qMmPvp4EKde-{HL&urju zj#A`*>g~A{c-^?0mh*q6_&@F^`Jae9`{7OEKNZe?SpC1K|0dyF&$ki3Svc!Cg!s>e zvz}9l|03WY5D)Y79-m;izZ7}S4^I-mHQ?D#QT{gJr}>C~O#F7?Y|r+ep?sKcXA!?c z1{iQgIUPl?|poWni%bJTyX@QL1@;|+c#@$*FfRJI>DtVeV5$-afDsii=FDE}Se z-w{2(^m_ga9M+>n&o!POycFvBjmU51`BTIn4ERCgQ2rj_^St~u#2*%Zw&%-_$8b-T zaN9i31HUYFvBCzgGBJUjJjj>rz9KE(dttxE$&Ugg9foNrGCUY~ka-}4iJ*QHL7a5;Z| zO!9Au{NKF%jw_*_upYaL_}@i-WiS5`@pptbdp`U{)bo+>jXZyv__{u_x)aZ4TJ?HLCbC??edvxwg(dY1R{ zR}lZLaPF^u;5q-z1DripMg8L>T^{s$t|$KRvRuEc4|kspojm6sw&zjeVLd-? zBa~lX?Bw&*vxtZF|F?*57|8#L_{PGw_3_wtW7JrnrPf&5+uKbiRE5^lZM{~7Tugmb)R)T90_g>$@)BEGe7 z*7IxPVg0t+rl@Bdk>`9{Bp#Np$B8c|@|=GrZiaeR5YGAKe9!rB&L{sNzMaT(z8%;c z^{l*HJm3D+^LV~JYy!%!B6>KS$2{l1Ioz*o;pF4__HN=0qGzY2Tmo#cWpcl38{n|N zQRLZg=MoR|`76X5MgCl$zFk|Po@U|P5C0kQi2)zKHOjXLKg`?NPrOYyx2Mk#-yz_W zzl?gq@^u06okX7P++-V+-$gjvxrq4Wfd8KO?g8I&Thz0waJK)u#HR>n`&Zl!<=X>( z4DmgMw|IZPPCP8{du)$-Iz*n!_4kQ~<^3b#Vfm_WKs{l3If?jJL_gnD^(gT$-Djpz z&vcRJcI0^CGlcK%F)9{PFB7SwZ~$a6h*DDlt_XA(askbjYQ7_T*3lgsHO;BanQ^c>{< zwt)Dd!oTAA*~CLTpCKOFv&BTzpAkL#jB|L-C;rV&Q&k)|=`2)b=zBS=bc|Ls# z@=F5#B=H{zf6&YCHFc@fCjP%8|IE#H=Q2IHVy?S5Fq9eW9iEr(->!RbFqJu|vpBsi zlgSU{`}0Nkb4E+oz(Aomse7Qmn9cX+hNh>R28McaL%E*JP_}23SZ zoISO(W&Auh~i z1{bzBHiWb|gm!cmC*>A(=LXTXDJ|^_9c$}?*SoWYVhKgWW>4$PILUO=&~Se--iW&1J%6h@(iDgiy0bfGbfz<{hvy*|6wx(>&gKkdfU0#w1C1mDrIu4v;!*i@t0XTLjcmR*-O$}T z(4Wh6WeXBZr=uy`znBv|Lcs0@O79YlhJtUV(}TTG0Ot?%LOF^)PB+aR?swTALyd-! zo`{)E1iG`my)l7S6zI(@%EL3xm0(hFQgQKM4$9lyfzBpnUOJFxYdVWMV^_$i>1Iex zDC31(UlwwBH!E>I2=aAYJQjy|F=(6=)t>1d=*e|2EN15CdIxhu9o_AtR#3^{R&-xa z#@P|(hE|_l8VmEYSTA-DKtYe`Z1B$pi%?Q$bY?1grBsj&H#RnAyP&d!stXJo%4fTv zPRKwNApuVrfI1j_E3~PAi~uJXG*97`;=JgLTc2o zqJ+8;D#Vh8w#@9VOmQfe!-tVt6SOyEI&;17YPwMD=xofi$0|x7?dc{~kjeKA_I7l( zW~O&FjAaOwZG{S(Dp;^DYI0LxGLX>ZiPf51V?ZU#b!(JFIRf!#6fMYGu_`p7T5cT5 z&80Gy!O}DXYTU*K*EV4d2gT2KRode8VeVTw5n-KjgF2X)Uw&( z;s8ZMiWeF^%eNxQ0&Gh1Q+OTnMk6cEfU`P49d(*Ii(EXo@alRAJsH+ZZLTot!VH}S zEL_cy!AiEU<}P^DmGq$cAd@PPvSG67c-xU~bk&NB0#qktHx`W0?$#*_XG8hNh=I2x z>y%s;6JQOKpu^ZdoatV)DBaYbJ2C^U@<4YM`qhzYDczXa&-J#k{V3H=C5}}J>%;_1 zmKO=^_^Ar19~wowD_BWb3cGfUF36Z`!7WfRs)|1>1JxHNR}5TdB*?BtS%~?B6MeK< zxTLmh5{y-Fl7g6glU-{?UCa(wa1@Q%lPIp#MYBxx_EsovWA2{{;c<*yP3yYa)RNDh zHb-SY|DdNGT8spqFY%x>v1_WYE^72a^@=&NfsL`+rb+{1Z$T;Z;Wc5|pNOd%FcSF}~ zjirtpbQTK5QWT@zLTm(Z_>`Vl>iDrUu#bp!p)xGVWjKy4xr_UxUU7xmG}@zZ37PGf zRjM61*}%f)%=EmDh?0Ux%!1hqnC|f7lolt8O$Jpwu4|C(;9?Q2P^<0|NP0u+SFOsZ z3q+SOUPuQ+GS2GO3u!fmgUm^z##wqC6O7EG8u4+f8?s~Gb~&T$FenmYj|;G;)O>1% zJx-r`8ur5?>heyVnjg{X@=hH+Rf$o#R*JhFx=%1U*1wqN64W#bcCAX!R8EYxLR@7) zg@C=PQZ!Hy zpB-8(6JQMC1K;_0z;$3lEw=`njLQGHK&?Nn;buzMsAxhl!e5;eB+{2WZ) zY)_^z)ZNhyW~94e773;)viV{GMl3YLfElQ}vqklO!l^rufe7o_$AqEt zBsEUX_b+f$B{&@w%mmU12oy>eJ@kIQynCn?GToCG_f*b3qp!F|;h9K17xPM~-r`(n zN2W{-7c0an*T$+Jn9iEgk~Hw69vDQjiYlVUiY_@koDQq9O48w_6Y5XDYLMK?a?2AC z?Jn1(L3W%ytt-~=in&kKft)J7Q!uiQ4ObD>DoL)%Vp_tnb1g+PrmSN5h{@Lwcr5p` zqRQEvU2jY3j6oUO)#KH@P|8UhP*fdIC=PB4PCwxc=$=>TfY*{Fqf;1jbEquZz2jtX zSyDfXw>tWn8j|_E9Aun$Co>vQg-$8-ach#tUU=+tE!~~%UewxVr1b3hgyjX4OLqnOzyV?llwrz$^A)HPVSGj zAthHvVh$dilX!*W_?!+jI>7=>Wg+>3Ha;guEU#>j?k}`~o{z&^&)nuBH+Z)$zWf&I+9`r_ow>&zo$Yfnb9SFRy&a49oc*+@%O`3lNty=C{YUoA!dbSS-dPJf;jPTz zz>)bya~lCc0|tNO+&Vxov)Gy~6!P=>+h=#rp4RP@$0r{fb4Nf??Dot4kOO0rlM}lK z`e4geu6-5>^`-i9ecgSyjTmxtTo@)k`(eW^$|eh>8(}YuoBf3Sb`Y>(csdPo`Tk-C zmvqoRR0qp+t+??50zrnJ(2yeHAXp|fF|2X=MKG++Gkvfnxo@}+X6s$;T1GOvC??t5 zKiroaf(>dkpN=0H>UwXCOytBG9NF1x63?UT>f!SdmC(p!u{2Y%@BIpCmk`I z&lNK>vNN1eWTR*^?(OB5OPfI{yHds!<`Pr>oZ_-&biZ_?B#F+^Aj&BP9*XUc_ODFc ze>>R0v>j}+S+pnv`#lQ-{jhboxHz-00RqMn5_^%%DLB=%KBq&RO7`#DeU#qqjToBY_pTBhS7=nia)Zi(b-338RJnt81LxvLJgdT)ovem#+PZ4 za2#Jv=Vz*9gldBhUZ}F)?Y&mUW@#+qrYCo?Les0YqFyO^xJ#)lG}F2Bjz33*qca4SOjgdAOvXbD@iKiF0-7eKDG# zqh3-$7$!xXl(0ap_B;iZVrZz6F7Hew7&Wt4zrk zPyzUbsA*&1@g^w5u1OyQWv;4p6{l0z)Cx!9297L6CIh2{+)xpA)k9CenD5GC=L?Iz zIu2K=K5)4SY6i9HPb88XybP$&Q`=rHfkv|{%0-h9Nps=I>>zDX23ugHihp*@@~tTf zM9y5bw=bMMCllFEfimC?Z<0?age_2CaxYrpW*U27Jm+-8VjBr6o{2+SqRxxH9QZBz z*ym2pR*^--<|F54qZuW3v@DWJ@pETBVAdRcHNhpZ_Z!>hXA7{0CBG2PcS6>IG9srt z2mFx4XWwulk@HX3|8`9d`dm6n;p@602%kpl#Bke-Yu17TbEN>ojWVSKOi)KdhCtm6 zc5I+6OtwIT%LB|A;TAkRe9DNcg!nPQXn_gMoaZGTYPBKFiG%yG+W(xTP=% z#T?ESL%oEjI3^CkiBwvWLTAK=Y00>E%f8fDMR>L{nAot*iEcb0m=T zNHj!kh$n-2M7m;`G|pC+%OqxCBeXHrxr@gw9o>9{Ga!D_gZmcoH!K6yt1a%#c%wfv z?*B|j{%n~|*M49(zz=KaXgR*4PMYI8v6JS`={;Fmt(Y;951@PZOk+UP6f=hV$drQ1 z+w!or9UErfuNB(7JM5$;Nt`ry!A@)G=!534W&eB+tT|Al=uzulx%|BOtiy>-oHEcm zFg(P;IoLXRc<$WXkbk-PAh-)6-LQLacBqe3NBN$)qK}d06G=SRk@`tU3a*+c zP!2Y@tCYGz9AjJ?-7por1qxY07S>y^laiZ`$ikH<6QehuQkYFn~;_p<3fR z24Dg?>EJVll>8)G)4}+z7Y;kAQxmvYh+Cj14GtIPgXP_aV`*^Pm(oqM=zg2Mv;B}C zhSIIj>x`HN5yvrgKiq+n+Yc5Ppl_NQ%FTliazpM_Fbr1N(7bfp9&mF9$HP4Z$MbAs zQmo){`QzNMG#Edx4d*=Eu@9G`iQd9sxC@X7D3ALlV6S@@;$GIU(tN&YFqOI3rpevZU?Q+$DiEKY!f=Pn_#UB>6mhl0Mk= zfLVwRv~w{M)qJ2mcu;+q70%Fm%{6(T{5$r28ZMoooW(sCZ!XH5ogZn~{=KAZkZ$N5 z$o5PbfK|(RzBtw5j>dE!oNk<(9qui{`YYVo;rt5ZPiqCj)m9s1aKjSVSCmOsAVTqNJId{mvq6pG`PFL<&}NIr75m2fgYS7%XADB zGBXEr{e7^JpXOqjKecrNqTl)u!`MEGto%A9)%IYS^H&`}i z3myKF0pE+H>He^!#x`c+d;SuFn%~3P0&g{-7Za{1hio4pBqj*I>Nt{J#ekZ&f0H*0JOV0Fr`oEOurd^jRIG!M4M^cQ`5=*w$0pRd?)_jz5^38kXdwbg#%$kOy?Gol!rH2kKf&oRY zI5k_$V!wT15r?)zF6tQXIk0IC{({X4ni~S;MiC!E@FLF{X|g3_vEU3_w{*YEaDg5GywWF%h!xOqlD(`hO3& zE;Q#SE!@*qNP2!c1?LJ~WawcVJnQVn*4A}zDXXQM_k!7wUYZfwtL?S&Y zvv&pt@|ihax9XJa`tu> zb4NfsqH`Twa+~YND;YESxg7@-hG4ZEF4Zm2?pD0T0kVPXy?3>@W_TYfG(tx23Y~zR ztj;Oqei)&sQip%RRjO_Rtjr#`YWM90TgdsE!%|W~DwM9!i64@~&WlPf*=vjY*drUR zK}!{9C{#$1t@T{%V(KOyw*)(?3!#+4qt(;~Sx{AVqc;r|!m=LB@t3nJUORJu7hUVF@9`_eEkebG zRqnUMe(aICA=vmd3~ixoz2qa>RM7QF-$=1!syWRz!;m};A=8wznhRzIL&h2Dr2?s7}luocnQ6nk9LY-XUu%p^`=u#kZqB``BmZyZ#@}(VxIyJ{2Hf{{zikDNTf>Qaz zUUw-KXj=xmXQf;pzpoCLZy?LN_$Du3K&;Czq;QUbLKVIKR%Qff;tYzbs~8hkYhXDd z{yL5y-5We2;5p^Ws|^)q{<&d|_iD!~fGRu1qYe%#EbLRmLC11^>QM*7Yc%3EP7q$B zkq6LQNVr?IltcK%>PDW1+=zU z;C$T{Uzw_6NoAIw({dVc)9sWrt-(a^icL52Wo)>y4hJYOc9{c*WMNoX*?=<3BZ=Yr zS!AU+9y~}?9eSDdk;Kr|g}C0Y@z6m+gWPjg<|L!V_nr! zU0qd$LO(d?%EfuN4e}iA&4p_UeX_#*59UN_OF|*<{qjPbKeZI>#qj0E@A@dE98XDs zg)|3hC5tJ?)nrV7ql!&stO$zs5GTGrpk@=p4X+7+#fNEUG@jVWE4z;a2 zJDBa3)4H}`siS4f=*dD=AJG6^axr&cc88L2B*pds7v1 z0y?iJ#|swjZKw&MzgS(soa&`%;YOMkrn|i8d>G8_0h$ONZ^xDH3`~}}IaNLXS1E$! zgTbg{4uzS9Qa^{IAQQmQm30QdQYj4(I*W~s890&b!QRgyK7udQz6IhYlMkn8M4MQ5j4n9%Arjz zahwC>BJUo`U-8Pwdb@IHL1r!Z<)V@u=nU*IIQx7IbWVerX38sWNMlDI>dLEnqiE~D-@pi?w`fni63{dhsr7tg|w;EgPfy!scoGkdvF69s`A#8`Qp!_-vfMLK(K2Q7vEo>k;ObZ1^(8-kEONJ?!dT2v=tL z%uiBac9=gfa5(i7U52&i^z^)7tbyjC>u4wHN@`>MkK_PqxI*6=k|isy{R3Sw%cY4a zaq7v8S#UwusX3F}cN(h@le%7`)lD5Yz63IPDpAo$mcR~L!px(hBwk7fOFS}MqQxxg zd?e^D^&3WH@N_r!49gFY0j6VO@W_!u;(V2_tvrMJ%mOu%p5aj5JfT3KK0pH*R zQ(?j0bZ8WVZ|Y2Gq!AoXuQ**e52nASLyf7L^W_tV6ZQNojhRtdI*Kt*Vsob64|nHA zY{jqffT?O1I!zHb@U zmUVAwFrBMi3ZLFUOVwMIEQN#QiI)1UaHR?$(pm&L0D$n{8GT{uho>g|)U(2`&>hdyv zep(Abs}-$jdA15XhLh5zr?H&j*>p=!9*^U~#_*i%n4E;OygWWAyAqKG>tyyBOC;kDco95Q@cG|9$d^#H@v0ajNg(+!dJj5O8rRNKKlvT$~o zPEc1~Q3+kH-2r6+PK{*tE-8fF!|5jeCZ{V1ZVd(mA!ku_K>0Y^*n!{D7-f3keK>k$ zC5^`jm%!2rHBWRXF>oOl!RmZL`2akLEjf{@#{{7Fo|l!(YCMEBi_`j83)u;WyIb3Mgf-cF^PN zEXXFXRD;c$+e=m^gld;DDD!7v_G>6tC=9@d%p-HR?XzINf)8vA=3>)$w;neV{_KEG z7M z7)8RAz7wX>N8K=ANg%1IQ*Z1&F*ld64FZ6uc#)WE{jV7c`(uyGu&X}_WNecpfKO?D$eL5 zmd4!ggLI2XI4d+}iGigU7piqyRGm@#`gmYDTF0tI-LeT-wP}N;BM()-L(?4Y+vzyf z<>IE=`&t&#s0edcX!HxJkV<2G1gq1Z)hkzE{1j=p$fvjT`?>C_WPL9Ulh}U@nudC% zl{xHQKsUDC-eZT~#HjFcBW7ys^~}KUVEFMdcYPp)QgAS%h`Ue9f0#P@2KPHvzKC_9 zlzJA9sYvd7sQ0J~$Yq?(vs@K4#F6NPo2_Ez#^SH6XpeQ6ON(CRmR4cmvYMsUYGQ?H zhzBu)k{FAEvNZS> zhDUpsx?#2jCLq!CFfO2fR6yyL*vA7pa7I74z#No8ew$P7giZ98 zG+YFQ1jn_=Y7-n@Q7IEma9SNT5*(gkf=7bV2@Z>3W8+vzA_}B~R#+>yVnN9cmRj{Z zpIML+-m1FhuEK;^6SFheRbN{~zIy=4he=z?Cy}Qr@$kq|4_vtH zPU%FezUVVEw5dL~?LUr#hF{Sn^S351h!teqpdeLh!<1k~i4ia9t35fu+CNg25(1KZ!RAh*#|@ z0qSI52|^s$Y{RID@)6kEu0b3yUbGdLTC zGp=x}mcK9|Tmh@tPQ*gu=Aw-6Dy}8QIwgJ_U&d=SuJ6?1JXvK*b|I`;ly#xJUX5Q$ zYg?sNuxj3e`odqRMN>+VRZMlnDdyHzo*o%(UW}|y#7*&wI#5iiSY^WTahN+q#b^yp zI@&-pkx*q!5*PXf3H<)mP_8T6n}z*LUB+2AsEcQJ`Wkq&*6AZIT&N7UWjgSX3-k-S z+`dt$yk<|MOM8tMqKjUBZ3AS*X4nz{XFl)-(K3_fkr(p)m0zIAQlB+r%ThHK*(%pb zYt%|x;HqA)t5tc@`ja?(bnd8jP00$b+J#gM$K88K*}^Q`qYbBY6cLv|L|bf)GrGJ1 z+te#9Z`h5HnpUqo6jH)G^szO^j8gBm*D`?M34!QAsHEA~^7HLrPNaX5thf4OO0IW9 z+mdzfX4GoAZ)7_*Ifx{WShK=Lmn~Uwl1nVb(65{A<^o6N6H6~U1ro7&xIa6zIKwl* za7jsLVWAA;ZGp%fZ**D>8W7I=ZpI^c%$*P8aZ5McAwHz1phFEl{6qtLDntOEm$9Gb zdeyXGH1HmoUQ4pRr@fN#@O~uh(M<1xn`N>XZ-0TS)#vqh%z`P;*_{QNgczGS%5+m< zelPS|U@DtFciJ`(&cO-nf)XR^rgE{=kKelL7^h(Tc-E{gl;k1nEAp3%+x663%yx&Hlaa;UPE* zP%Pah@4_EdK7z3qeXCUa2@JvXbB96A^s6PgqV>SoX9ll-PKOlIz$rR{Bgk%)5fZE5 ze1$3)pGT^}XeCRlFJ={-FIxrYD^|hqekAPCRKfVQLRjE~dNPEbYxbCSh%|X{3~Tiu1nmc-MvuQkE4uLt<^R4mkDEF6HF+$A zXjL+*T0Ev%E&>{x8a&WWiEdX^ekxr0@@k=utM1A#OBIF}pOw}gN~?2j5u(hry9%S+ zdAZU`9W>H@6RCPNw)>6aR(cB?8>nbu4a=?X(VB2???AVEFeaDNB^@t=Fk$|u>V+s? ztx-48=;a_j{cPi!L7f$7D|$r(iBaB`OnrNnD89v%VfK|;p9#R zm&o8-$3vN7c3yiMX9-z8rUhy2=)v`UeiMwHh-#c!UdT80xa=66u*53~!g=9f`J#;W zxV}oO-!TKY@`#xxv-`;g28#pL8CaV9hbEgkSGB$;=8k%u36C<;e&cHPs>Yla*{_N- z)P7LKVvwXsYXW+5n+B&mxefBAnZeS0bp)fCRUC?_bt*UEP9!%#v{&+K4PvB@F6EYp zznjtDZXj0a967EflqwOvajU(jmc7Z`(&(^abvdMy-n|`}7>#V-;9*d7>N8<)YvRmj zbj~XBk#g(`1%2scC6RGQWhKcIc(s~hXz{lA?;l17U{JTF8*nfA!XkdX$W<3!(hrx~ zc+QZ&4CzF952>FAgU>GFR4U76y41%?)K7JIb)UuPeD{Y(lZK z$7uEYL|)?FsxC8)O>Fr4w9)z*u4x)Y^(<3lWva<&EjH2BO2q-#09Bgo!iEn%baZ&G zL}k7gP+)IIjKr5Q%~oIDx_`CMd=WO=HGM-pxur_5Erpw8czg*#2F zn6!v)qU|a(bpaLI61a!QO(MA+>~t#&*xbs5>y*cy(2RPpb3TY_ISbSd$Z!LW4vuGY zoH?$INPJF4g>#pQ37R~%=9HAB8g6)7)hHxGtINSq1a@Mm|18H|z&;^0t!-gq>hW>0Z54Y~&#BgbxOQG_+jXrdF8%(JFZ3r2M;gtEyh1^*b z59n$z{E{<#dH_G=oE^#+=lA7``EJ~-0EN|UY|P6Con243v#6Xmwu;5?W2u(M9itl9 z#tK9`F3k`0N2imZ&(==|z2?;-QHMT*ixKKb%jY}w?Xq@KQweu)CQds87 ztuvYxe>{n)UN+}!s<$wqK^gn(lNdSwFdZF@jpacZte z`$A{+4$sT?>+BLv8AUF_;M)PXeF!Fu;?m9i*}howRq>s4Lth?tGY%Y{>xZ*?=+LTz zgID1I^2lCoguV%W$9w>~J=`Pq^>SsC)9~_8?ug<1P_C!E&5e_&zXSc~zHC2qf*?#- zLtR+R%+K`>=7yl>-ZGdSf}^)E*XWM9Qzzb^w}xR1tja?^qfOWj20^sm0xIGRE^_m zigCKZB^K@C#;oWj^Q!lI^83|hEAO(%3}VH+$bPFj5Uv}zpHw~sz7eK6AAoetRRFv* z(kj5cI-)87UmbB3fG<~H1w@MmzB~Hj30g)`JmKw{iYLlPo2&}O6U`gr;t488RXpwY zt13C@0=H67L-E9yyx*!0q_*OT_ghgXq`LBn;x!jgd}*X5)W18TB1-R$xQx=pr}RQi1(hru4?7+Kztca&u$+<8`KG5%SQZzy1ac&{wDI4R__jK>TJQ$l1EJa{W zCkGeqe5ih=E}98pUCw6|*p>+&z*&^-$}ddA)hL;TefbP6_Rz^bI?+jzWsIn0)^Thi z6V?#Ri_n=vPE%@%d4#tjn3igekQ%zP`I+>+VyNiCU3 zhdGLBSXkf0HVn6pM$#>8n#dD$>><)FMc#^*X#FU;St(g3jRhayjyEeT8f#V<2Teq+ z^`2F0m(MVz+7hlajnbp*oZ$M$E0Cbq(_EorBC3=8`j)C|t0h-7+4MnejsX8Dy ztpk-wXRa5fQqu)kes9SDiUbZs`s-sK6TeRl6c=#yAHUD8V-8i45m}I&lg93(0G;!5;{FCxxT^TVmHNXc)lq+L|Xzni*PAIHx|$6c2Ou6P{G5c#B=aN zUa)TzKQlt-g8Y}83xm_SgXNQ;bPX!rlnNV5W<{oeeZMZg<+gj_-ZMaPOV4m$-{ST? z7A|a$OpOQPy?8DF(;auM#3#I~hso|sv}uirbt`@fjivk z4(R_`Rjzio(XJTCCUo7VRI}LLC?Pxq2SoP&ne|z`4TD-hbpEf}DP?ywa?%p~uNq7l z&Hs-AY^(CiH`OO!bv*+N7f$!WQeV<-i%=E04p77kRW#i}LN-;COGnjPFoR6aJ5@x& z$o^HlSw1zZRA47d!KDhGcPr$E7UtZ3NxV#Ia1c+(!QIxhgVI&t(RMTO>hgFi=vvE( z{R92|!!WN#>)+fOBz+|yVZ?$hga1rGX`6BGhz@AxA^t(j3X93KqKo6{{(+%BxV4Ip zox3gqw271TS-SY(HhC(GlaP&%uMgwWXubyzw-*{4-S>~@=7-=Y-$1v!qX-TYR=3iu zG^HovAxvDs@6F+7B;Y@=vjgo1c6WkiA1)il<{s}Hjx;fFnjY{(z_iZpqtM9Tr=YLY z=dqc@4V95&iNSy@**UJ0hf`Qmt0X0Eb)JUi!X^0B{kI#+&D~DVE{9#rQkbROiG7+X zawlw$p}t&V?u>e;C(%2l5b<#}L4sUTn5BFj|IX{!x4>iBswY>7Bk3Yk+s1Ud44A+$3bX%I3c~BrZCsfrw)t;nP zs2xGtRH3yxC%Z<~*Ro-Q=FSD^!{6xyAsVSigujhMpBf2{)NvEFH z7_E5};W4`(G0|F?jHuv)>K8wfgVAm=?$b(q5f9V`Zv4N$R4dWevADHyI-d|?Wl z!|Rqb#w&k?VUl{OxJqjmV;=| zA2MnPW}ad22u9V^g-lo=;O?U}^EP*Apr6*@X>#7Xq-$V^X6Ri;^GA*v8*~>r(=$LT zEFIWYPEU+H!u%JTWDL5_Zk54R!}_WaOOPtWvVzuXhYmv~>Vp~eQa25IufA^dbEdpb z!P7nPGG6W;nURO9h;Rf(_hq>OK;&~=L1*7sP%g5 zXywL5k+_BRi`k0DW0V{Qx9sk`yDUg7fpB!Qwgl9>j6l)gDj*D{`lh*B??rNcxt`II z2wJ<;=qXekk5Ts?^ko}kcfoSi_S-#*NWBu~iBT7zG3;ejA6p;j*z`QA4_4*4@~s?B zd6aAAY8pe9+8Qp}af^eMZ(KESqe`6TihK-fMA~3_X12e-8_$FPZH{Uo+ABiR|2>(0(1fOD$pN01e2jzUG=Ih-Wm70)liaxM;(Aq=_T*5>ax@r#fKZt zFqfI-AZTO5UBrG`aO?&T;jjxDay68PJrpg^#u!^};4s+RBIP_prX*4eQu&qfV*n z7>#l~V?n#C%vPuBO4OW%sb&FV)S;-3R`ZCi+KuNwD>@ak{OF@nYCe~6RK~8GR;~BA z>*l`NGKM{o>J3ocxw7u9zI#%0*mjp?i3B?K{k|GvTxDinf)OvBE~q%wPfNi()o)CN z(1d^VNB|r;h^+zOAp|#?Y@;nzrPT&M|4?z^fK1`(jL#yRZLV>%$e}@ z*L2dpaa>~5xvZv0!^^Q4G`bkn-knRD`*7=fBb^TmN?y_^drUirNgenx?-(WqGU6$@ zYMkUxKH(Hy*&a*PJ2i~yH>=dXOg zl``!Tim>&A7#;QBm_`RZ`fdPMSNNjPb z)F1di)rU9g!)Xynq4)wGIAT`k?tXMI>ePV4jv2U5G2b`bH=;e@RXYiD8r)N}XyhT) zI%uJ6>jo`$8rP^)rH0GB6Ls!|@8lV|7mtus$h|dMQf($4mD+fRRuzsK^_D+(HFCY^ z2D_|)+h_U1Nn@77U@D6yzR6fW~A|3s`-BSzx`R* zk=fIYxtMC`5sdC&aV%*l6O5S4jb%m_tZQ+{S}zYc(H}5QON?B6oL2h?E8glS^_z5y zAIS%4|BWcP$Gy@wqPk|oQ8hT&4WBYu;*GtZFte&lZtRo00;;w^@4C3VB}==MkG6jT zHUHjF5c0)5oJ%~)uhNW3a8QBaE&l$Hk9WR?JTxTFJt#SjA)! zdpLF6R!G}j@Kel z69*=$Hj?}lnWdn4?#SnI;70E}o}(TdfRMXKTJ?7Z9MPjSJr&NkE#Ju$X z;loOLaxwB%o0gIxr{sLAfM=$K=IEM?@|17#TP1`TCNoC z*A@S_l0QfBj}*T|@uifWYYl#j;`5ZAyA?k~@uwBn`rk14zZBQ{$1mj`pr7|s`Zrhn zEyWu=UmoPgt9VUO@<%B713e!H@>{_FUV#7MFRSE-lzgA!1;w9=>8baBzo_KjQSxuc zvTC#aqWi%20vPH zt>+BIwVulq*YZD7{B`BeUn;Ki$)6S1<@964-&19Y z%ogxJ&R4rCdF}scifcdoET)I^)vuJi&Q}k`8KSqvN%);yPb_S#j;>iHd7K?4`Jt?^Il;dza!`PeF05=Oo3o{6&gu`70II`S3=? zwLPzTj`?R*RleRg_)=d$FNfuNEzjBi!@gW^q~x{#Cn>&~3U@EXb-eahT>D|J;;Sn? z!;0&Ca=PbiC+EX+mAtm|0>#%*`ma@dO~vn0T!;Il=N#@i-ajuWc^z(QnUbH^Qu@E7 z`1`7U*j#ZP?hc-FxLi&rD|sF6o{H=E9;mpE?||Yu+><=#a4+%kJwwUsaBoyx$M-J9 zb$nk?d~M~QcNJep@uk66_`__i?OfM$w(}ZqXPuJQcD5_7?Zi49f2d#EiDBUnxwi8} z#kHLmDX#7OvFB{(?cUCxD|v0_bBb#_-&9=NxeWLUe{nm}Hs;#S?G)E`PVt=WeAL@H zP04FJ2Nc(Keob+0=l2xX{``^R+Rl3v*LFVRIotV?xAPSxukBnKD@gdEf3%&eE3WNq zP+Z$NS#fRW0g7uo2R&yy-}QDbQu5l)ixt;)Uaz>e^EZmG3vuW1!qbYcr}*27Yde=- zf!rhQ@2B3*l{`nkX*(Mf*LLozxVCd&#kHLa6xVhhuei4JLeJTs%i@2)?@}eN?YviU zZRZn;YdhaoT&Md|E4pyd4?5jfS6tiqWzX5pFM2zhl)Sccf5o+(a~0QiE>c{Fd$#8s zF82>FRPs99OBC1b#Z8Lq_TpZ}b+|8h&f%`%G*D@xbAl~8GN$hx<9s$;#$vP zifj1+#kKs`4E`;}wVsO=*Ltou_-%@7Jr63b^*m$nHx$=;K2luk`NGO2|7*U6;#$w9 zifj2sgYT}m)-y|SttVsfe#Nz(V-?qW&M^4*6xVvLQ(Wu0)!+{(uJ!y;ajoZdga1=; zt!L>kC8x{kifj3L#dWx8gYTxe)-zLat>>$XYxzFKb^Ug#;v1@Z>{`V)QvA1yZ>;#! zihoJ*zbL+m;vXum>+|uel>DjrI-YYq&+XbKN?zCVQx(_se5c~t4+Dy8J*O%D81#X; zpL4e2bt+yzQe3CY?FN6?;Lj1twV9IFe%MQK?a%!c z*ZwRhuJxRuxc29Hiq|WD{!DT0&$|u&n89CBT>JAqgMX&D_U9K@OZI2I=j>1JA8xJW zwI60EuKjta;@Y2!71w&sRb2b?yNYXn-lDkn=e-7h!r*^WT>JCy22ZV??6)r&d^6A4 zpFDoqM#*bG%u-zYGo!fn=h2F5J?AN|{duwCy1d`2xc27*2LGeMUsqiF^PdJ^dW~d% zu5R!xJ!gONxV1saYd_3UT>GQpL4D?@(O(^AUqTZ}7h$zBQ?awO|*Z%yC;@Y2oF!;*` ze^+ts&rc1$(pt&>T;Jdgp0huBo~ljBYd;*Kxc2AaifezKs<_s3sp8t7*C?+2d7t9i zpHCY6HG_Ykxc28#YnS|{`6`MZq52^k8@$t6UDWkw>S7y&)Lts z-Z5RtYyS)?uKj$R;@Z#OQ(Wu0S#j;>+ZES-eq3?w=T{ZietzHJpBsGT^^*O(p~1IO zT>H7j;8Q(kKl8lVbS1C-vp{j}=Y@)EKcAtv)^oYy+RxW1uKoOL#kHRwQC$1^8H4}X z;O{H0>y1wgzSjDsbkXbY+bF)7Dvxc7YdfbZuG6d2b50lD_i(V1*ZwRhuGgcFQ(TAp zO~rM5zpMD>%KmE=pP=|J6<wQ!7o=_>$y{Lt>$x??hr^j?Hk^4@#`vpn=J^25JV)S+KMiO6MFnE|181Jf zaOPEX|eIUjcz`5LKV|-hTe*))nzm4(q1rw5gqUVxaZmt-=GRAAdx!h(k-W|^64vq0i zF}?uK<*teGEpRUP;~4)w#?xPRrf*#C#W7w2&gE8*@#|x}JDkhCGsYi;bGh?kd|ixh zfpfWgV*D7K%T0UvnZD64iSZI}F1J#QH-R&Mrx?FI#z(-p+y`U)aX6Q|GR8N-nSU3Y z=Wk!bdH(i0oabX13!UjR-}k#Zc=Q@aI-Kt{M0_!LJ9u$;FF410C!FsePK5J)>;-V< zSqo>Lm*5=NC-4%e^9Y>F%~tqKe@Y@gZ*c8THN^9JVLqJisXhlkitG0s@aP>Xe-5=D z&OV%ibGccIoT;DJDS6?{b7hQIi}CAYyepjRr7xW8Wj4GF#+$Y1nfiG>m>bT1mWH#R z_2KMiYdHJR56*s$hO?iO;morz##h1FhnL{YvlY(x-{9;|&SGc!#_jQPIIrI;!>>XA zJHyMvZ-?`G_U;&;5Ik*CSy9Q?NB<+~XBy&po%%VIgyL3j`lLU&Ue1s4TrplK#!JJwpRXF@b%JL~s;3g_Yyz(gZ;L!t;630R z*WehxKgMUr_%b-hwLZo-!KQ0D-6P54B3E%;)1 zZTQ=8*0~?fI)8%KL7p^Mo~e`T@me_h**>_h-zUO)>56#vc{rSXo(O0CkHK00GWZvm zCojY6VO%@l`w;(WaIb%3sQ)P9Ij??)vk!Sop6MIMTOQ8w)`N4rt>7GQS2&kDIJnpU zS*U*m;#tq5aMrUF&U&7Qvz{&RPtni4@B{F#;r!fUrc!76b}iOdJ~+o)Cb*CHXc%uL z#B;o@;2dvPILF%`&hd_i*GHX?z**<=;9lpcQ0F?tv(6oG*7*sXb$$zHohRVz^Z8eu z>2m|rUn98JnLX^Eo5c97$iwm8EAi*1v*nFLJjc5L&hf5+bG$FZIo`M7pJBcohO^Go z!F{}!hB`BpKGPr8SrE=TOT$@b4LIv;1n2hB4$keR2fQKH*HHLDjCTT@`4_;iL!LEo z_UDb@-k;*3Kid({{v3w0Kfl7+pL5Hc=`;J27tVT02lsl)hI%R@p7peZv!0vbtmh6m z>$wNcem(%_`kDpj`dSX>`q~I*{=IOnuV3NOXK?&_^W3Y?^pkzd7u@?+H}tI#;@P(v zaQ3Y!oPFyEXW#CEvz`Zndp#{eJ<}1-dRD?&&x>%@^ERCIdMf zc5trW;qWGip9p6k76kV`+!Fe*6!GlC>u~mAH=KR=9L_%c0OxsTu5xGkP!08$fj5QM zg!8=dW;pZQ4QHMSaORl>Z-(VQ4QD^!4DS6L5c;_T@$BajIQw}L&VFXR=1hOs&zx}9 zb7gR^=l)PnImEM`W^mTi3C?=@z**0I@aE{-Ja`NE+cCaB#?LQ*rVq?hDaISc_$c^p z9KRlq@#kWESBz(>aHh`dG2Sw8o)iT@V9AIr^K z@l5@^&v_NRCB{`9-U{9c-Wom~&Uw2exYs{5%-hw7=e&Ij&Uw2R&Ut$n&UyPAybbD1 zTj{U+a50?mdEx9^dH4;;-y+7JfHVIxIP-6WGyXL=<3EM7p5J2p`pRee&=&P~gSUg< z1!q0O;jCveobivq8UHk#^}iG2N8z7fp8pBI5%uS)a%Q|ABfc`cJ>r|gzeIcw_~-C} z@Kf+na9$rRfOo)hUx0Un?|`$Pd*JNn4{+v5SM^LEnCCn=^AvzHz9^jW72%Ap31@tJ zIM@4KF@7JM`yqO*M)O_wvX}taONKi zXa2|Gj9&w1{B}6w55gJ$9h~zdL(Mb&VV*p2<|zedA8Nz7oi>B>e)Y)U(S9bnrRCf8 zSi~RBe8wjt{s{abIP*LjJX1nK!Z(P2B6t)VeTRTAH*3;=M?X<~IqYZhC#%(15ndEt z4PF3V8=f70HQeK)-`US zPt?hN_JSuOp7j@n--h^bnV8&9K7Y@Rc#b!`rtvTRXCB7aLLQEb`FZ|REX4cykMAGC z?b77s^8BYh^7qELTEbb+O>pj4`@tDM63+Ms;T%_ZypUYyov5cV;_rgDg>$)GgGbxN zAjIDt6F(Ntdbl589_|OaA%AN2149v?h~;v=ak=*(z69cj!&4JK67jW>hs(Vl&OY1- zkK2w$A%7y`nV)suhxl+CHF>==p4;hI#K-05cESD>M?Lo=PdE4k_#JTe?O8bEUxhP% zSB!rVfO;CixgWRz&i&8L!K3}d6UZ|Z@yzo8oOvFG zbA9E5H%9)V!K39q3D>^e65_bN7|;FBQsha^{%0BD6T@<%^~CkadByWI-~UAQ^L&rT zwbjV)>o>|zPfYsn=trI7U5`AenV-)gJ~27F<>$C~p3MB*&ul;*??W`+7vZdv&h_#v z;#0F;UPgRe{ao&5#HXe|uOU7z|E1{L8;HLSz6Bl^e>vjcM0_szHaN$%9iEzT?Ld4Y z@^iiWdW`1VPQ-J+!RH0Vk%#X4rzj7-GvePzer^{Z!F|3(^XhAOBJv!9^ZbqbrJ9JR zH;?h2aQ5dOIP*-4@x?LzG@ScGA8*vR=({ETxRZ!@*5mQopDPg0_j|)_&gA_Go$HtG z=QDoXSr+p8aUrVnTh!_210L_!EkjTb<6jEy@vn#fej_HH$9?ucLmK-BQ9bm$FP{S2?G{7c_>oMqpdp?-R&;67gOXLrQ2KmFl+FPF#Pc&wuD=d%vp? z`ZEZ1@;EgZ-X8Ho;Jx8P;XLl#4d?M?82km~;c;*${2s&~hDYC7?dLxy;djB$iP;Zd z2xt8z;mlJV&i*%ob6#;h-j4bI?^=(E7%%r%+Wh|HDtqtdWIqnChBM!HWh!~F*5Rd_ur`F!Rv+uHclxjhdH&P-!0ml8>g4vm1kUaKDLA)xdffKT{m)Y5 zp)ZT^<#66F>JCrM{$vH>8({u(JBr(%u+CM;!+x%Tv!74H+0V6b_LCmh&+z(E@_uq1 z@^r$u_+IEh_%nzv3Fmv))!@$}zAbz`ya)U_IPYIQ51)v5_H8MgeLD!>fIPWyzQp>k zf-^tQyV##5i06CM9pD^qZ#c(01pWf*90%VBe-h66H^W~<{0=zB^)sA#{QJ41^PiWH zColTB3C`_{&hyWg5nl{>=;h$d!}B5@r+8ob73Al3_Zqww^1lIZ0)HLO?SkG5@p1KR zK_1q#6`luq-h%Ua8Lu}hBK~c}b3gD7oXgz~=W^eLbGZZIT<&{tE_WxK^I;d9`@P+8 z*7-g>ZvXu6y1wB2*@NX)MxQ@~*M)Pv^E`ha;>*Rv7lkwa8aVUwdW6?OS0R2smdkqR z+40+gx@8RsjcX0NBo|-=VfIJ-UDO`7OzWs=Jo)7SOO?~u-p3UJGsO70F`g;L&x3P6!1GV;2Qnj` zeW3SB#dt439&Ybh;XGci!}^+y{5&692G52(>){u|KM0;S>CdQ!jp+sUxIN>f;0YMcuvH>1kVM38_sbZgmYXc;T+d# zcy8q9`AlATx#aHr>+?j;f5u-E6VKzyCQ_k^?meE*jH zABTAM?Lj#E#{1RzQO~7_F97HHKb_~>iHPU^wjiAOFM~5bo%t_EJl9JhIL{M`!1G~T zJm28{zZl}#pAvB9zXHy2m4uhYa!bK$!>@ujg-5?L)c0>);APmLqhJ&WPBk)QXG=*5ltd79CINuOOa%&KS;LqIlMy2hKXLhO^H0 zaIW`3F+Ky%I-i8s!+6)gSpuu*oj=3b&w^0{l76&rwPL&joc-kQufG=c^Y_uC-z zg!oo)?myeWOCtVycpZ3SIG;=20KXaWE#TZw(#Ig4=Q)$%?As%7p6Bp>eoHKO721lR{I>|CR8e$n!k%aQ?pz=ltId=lnke z=lth-=lth+%iXAl=PmcZc^nxIXP(CBv&SceCX7J*#i34ho>!mk=Nv~Pe@$};4tf4JmplG{ak-oi6R=$R18|=wQU52x3! z@Ay1|_fg|~8tP+TzVt;EX3ao=lexm z?rg+!K0gX){9|y|NoSpO*7-Q{u%C0_asAALam_>gW$^iMo@XwA^S;CraQ0yloO$>; z1;5^jw)ZDv;upiY+$C@>cPX699g*?O^)i>c4Dsy4a(G4bhxfsF{l)jJx*?wLYmJBV z{_|Dvidb$fIPceWfb+hSe_l1}C+nPr_?5{29DEi0Q#kAV4$l1vKPSTb@a!AM#rsI? zGoK4^TobTdj%zNQ{pWoK_Mg`g9M@6gS&crNkLv|~p6D8QO~ki>uYr$+KMj8j&hf5< zbG^R-XCIEjS7wvW#r-h;T3pl@@z&t^SlOUe;&tqP9o}mJtlr@jK}49D<*yi zocr6I@N%eU7o5kt6{z3yB!#B<{u7RCH}dc~@BP?s^ZI%Z;@gILqWpC351&Fk!$N$t zU2vXre>D!vu}*Gx4l1ia_^0r`!J|A?P|rPZ=I4ICD&l7#o_$Eo_HqFAF#ZcT zx8JW~oY#-sKO90lx9h`jUtdX-!24a?UK(LN^8D~&czN`J@wMPbuw3Sk+a5hv&O^@If7d+ca_{(GTrT$~Ct{Y%>o|^=o|@~v-;kfn z%>(Ct?DrTy1?TnqAMmQ!51hjOrzre1;#tq1F`kh5%=H)VGo*nt53i%+;#m(r$HY9m z|H<>obFf_Yjr)1VXG}#r@2g}+d`a}JB>GbaUJB0Zqw|pGX2h39{Gb>g1HT0Eli@s` zJ_65)_@(eN@Kta=XXo}_8S%cIM*FcW7#I7N70$kuMIQF89Grd2hCJ+BdBn4C^napn z6|mg6zHuI2jQZoY(>s$_$c6a&s53V_HF@$N zo_X@ZFGc=*aQ5v|cw@xphZlzzfV0nua6itbP5O7yzG!DUOThPXtK&SD+eJa-;d2mP zzxaKXq^XnQx`xM#5$JzITYU2SSG?Zo0_XnioZwOY>(iXsKXab&{5&xx564vmEnE2Gp&nr<6=VwVc?@N?| z7sGO|g5LtKjP=X?WH-#K;)thT1Ltw@IymFo!x`Tl&f^99SqAlUK3omwJm+-*=L0=8 z^PJZashQ`|JF7kqSwGKv6ER-SAC9X6#>IKg>j;jEUNhv6whKDvd0FKDJM)~^1&Lv~ z(e}b|@%*YfmdpO|ypj9c0@$v(zoql~u|`b(nlaAjP)$*PEyQ#Cstf0M`MwkDq4T)F z`F{hJ%lTgfULM;i=k2wqhsTi$h;NHL%+GPvN1oJ-YZUem|HQZ&qMoxI*X3cne%#y> zj+-UK4+Os&{b_{dvJbm45BdJ>F!b5id$is0IP3MRbHB&qDeq%&eQ~?EE~cIj;1$BS zqUG{9$a?5KW8xNYa&0-_nKh6)IxkycuROK_LX#(x9ndQXgsN&1QE;r+nWY+pQ%b3W6#eepQ{ceXFy z59Id6<1Fi;bNiyFX8Ypt`fRtao07Y1edckE=Nr6V#QR8mpMl36I-g(gJqKQIw#NM7 zah&&syl>HbIE8u6JZ=6)o-*je4ajpHye<4LIKO9pKD-^`H^7(C92EP$`*dJ~$ zjBkII@f}hT&-u_1@$^nHeiQtnFs^8`FPij!S4Jx|>BrAE+^Yu9W`CU!?aqFQ4p!mE z?;AuOooD(_V)!4CS58{4{}c=VBl5?R=8ymQ{v`6wh_4s|BJTok0B1eT;gt~Y=T}jl zs_+qrXP)u!n-M<+-W5I*UJ*VIUIiXFxu4N~#`~BN@sWES^lr$*^%7mb_>bp{#(NFo z6GK4cas6lhiij_VJT>9v;jAZm4(LCuC%W$TpTzJ#qI!xWPcitCn0eA2@vO54yaDpC z9?p|uh;NJdE8rvG%;W1Ps=p`VIZt}QXChBg_&j(Cc;MuD5}gNnA2}Z)_d4jkk%#Lg zx}W1eo-eAu5aJU(t zFzH9*dmAS^&j-AoC_WnR+4OBV#>Kvs@X3^vlYP4ao*3$h=1Dd<`&Jk3|1*leH)gpb z;9TxVIF~yL&gG7Vmqwjq;1%Kb!E3_D!W+QH!JEU!!`s5|hj)fgfcJzy03Qrz-$uY6 zMErR8MEDf=B)HF?Xg=Th7u&CTt&k_0Z(kz51)TH03!I;ekPI+)ii0xt-2}cSfGs@SgBT;oMHyw-Jbc4DsXPkHfj0&Vl=SjJC&HvEBK3g?g=! zKU(kaBL2VI>7U6z{|Vb^^qnNWJ^K2M)>kw?-4n4MxxdO7JlekIVV-b1oe$@Bx&ZF^ zqdZT*iy{9)IJeV9@YHOlPa?hn@-K#SJ6!_jcKQ^&Gx98j_k=Hlb30|W{R zz`32Sg!_7ow#Tm6?zo-Oxt(r9{C~I8|D5gg;+X9;nxAL0ovy|_;dUDR-a7x`c6tP! z7y_d0bPe)wJEdnt{L_f%a--jG=s#TUyYR#ipvz_cwK4fw5A#RAFVcS!!~cl#zYb^q zb!VBM%VmCgT;EEg9>!OU@tQH-AjX@+qu(p)KW*X9!`X*tV*0QQ@$B<*cp~!iehc$I z8hXAAZj>kP__z`EaQ=^ucGBU8 z;~E1`41XWZ&&SYD_U*-({Ie0y{Exz!pYyF4mP_YyUy4~S$?le>0r*zXoUh{ZK!*>(>#_dftF@o(x4E)^j)fpQz`}n0h*5xvZxX zob_x$9$(MVeBPGiK2G*wE8>~I8=QUSJWNggw~&YVxt%gU=UZy>za5jG_mi3bZ0mm~ zCO`Mj%pX_(j-)())&K3t&+)z&6aOyaJzunbxnD|6o}K@uJiE>^Pux7*jXazu@59+= zo`-O}arr+$o_`|$o_|yRxb^-a@^iiOJd=Hhn{OW>Pio@#o@M;LvyA^ZCO)nY`w`DR zd;;gV;_`foc;-0(PfecB5YIeu^~9~0gUG|>#>IbrmhoT2#K-mLOT=?rU%^>tT%NBH z&pe0VejOd1*Bwi8Ki{Jt{|k>!-F|}exlEU&ay{7Y|IQq%o)4@Fa+;M91@b{Q7&mE|T^NREK3e>~j^TO?# z^Y&WAb3Slfzhb?YLw`=f+ak{lY)5>5o_Q9Bcz@sNr|`boNo_XfNS^u&ae*?}w?1eMWu^9g|#xD-*U*}<=7_SoJ&0@TB zj1P?Qk#O!erocJg`7yp6&OC*ZXUV_L6Tauq`BMY&ld=D~9{v!#6P(YZ2gdllaMqdP zxQXqkA>#jlKL|e!=eYiamq9$odlQ`F<^GoA9gcX8cQ!mB>0sl>(`9hRKMQ9cc%0&K z^S{RtdtUS3)`$NdN30J#j-EQnf$C31?XBp}| z+v5nYoBn$ov3c^})`$NdN30J#j+}%2a82xo``|jLIXna6r^C;M z|0f(@GNPVksPk-(FT9_|`^K4(pZD3az>8wJ7r@KH&x6;Eaem%`*Hf$~8}hK8i{Y#% zJDl}g2xmR?xO%wW<33;ifARCbsTtP?na*4n`{!1Y=s)^<130eg*xpNG9`g6gRD$z! z{k(sY1M{aB;xB;@gFlA*uKXM~?+eXDeBAuciTvCy=3-oapCno@xe(9q?O}XzEO#OD zTm#RIJhk9g;{MF7aK3+aCp>OkAEQ6K-?bOc`}TQIPyLwu{(K?o!^^0X@0AU~cvJIU zS@hnK-xo^6a`_yAeanYB8zTNvIPbslerX@X=SMv6n=M3t79pPZyVk*ZT-XffJlqdw z{7E?bz~5(dNm8@DKe=$<5pVSB25H)Xb|Qi2o<%Rj$7=uULOk)XDFcE)M7SPVjuMBGzvS#PdAr z3OJX0C7jDG1?O^kUdQELg?KKvG(2ahGdeEt{(J${|4)2BF!Q&-ai;|8;rq{tsHY6- z=W#IZd+Ey|zAf_8??Ci<#XnF{|1$H7(bJ20>r%{EB$y;rkVXk)OY3wifzU9mh3}t1Y}X;s?Q5r~e)qt#cCMS?6px z^E?$?^Q=KU^X!6iya(YN@8RIleCB*O1?PNA9~F}H6Ro~F=mUQ*Jh!ich>za?_w(Ls z;GAy_;R6ug7S8zF;EW#xXFd1BSZSF*uF|6 zcRwK^T3Rct_U8*cSn4C#5X`Zzo)AqoZCCEzqq~AeS44UVLv~@a&JLB z$KZUw^iOy@#An8QWH>*7Sz(**G~;XL1H6g=vGbHsOy@gc~Q z7x81@9B*Yf&o`RDn;}oD;88s-;kU;4_!xgGc(i_bzOfF@IuqeM-|+Pk<>C1T&nsG? zPCrkJ;# z^qMj8ZGuPJS2yHm|G9sgfOyu)?Tgnni81kX9(QUYKJGZu4|R47@lhY>JdW`G?HJ_e zJWtJWLpWZGrfqi0=)*8$L03G!J>d=pi_dFLRM+ zF^+4?-~&+4CipVM^ZJqVnfr}lsFV9co{w?ALFfLQ`$O)}d7joCb#niZbPAvRle8;L zh`#gL`^@#o^Oi&lPrlA#9*%1y#>M?1&+9lYdYzCzT3_^bSnfT@KM2n4bTXWEa$G#` zN{or;xW;3-^a=2PVm?2B{G87`Py2Vx=a_n} zM?O!Y{&ok*f&t#p^$KZ5u~ z^pp3WOT&kupT571wmY78H3{+R+@J8gi}$73f1a<#y?0R-_4|F@Xt_LJVm(Zr4p9g660b$^gc21kDwlIUrXRT zUT=bP``QNQxbngmBsIy`OBwhQ)bD+cw%@1VHz0l~oZAt9zx2bWuMm}5BvNq^03d$!#+QQJnZuwspxZ2tgmO0hsXEl z;5?t?{+aPb=9IdJCR1!w-laOUUdO_;v~`o{N^_?{cbTMhAi zf2ldVFZ$LR&fjm#>!3PVkMz25uE$r=XRgQ1aIVLGs3$e+@ipY(dVCJ+h3k>~XRgQB zk%#M%`MDmMpX-tNxgMGSpIDCr(YJrsdb|qr^9}UpNq7_N&zHfQ!e4~f!aU*es~O@C zA-*~M6rAr%^Zm~jh_8eBd_BA!obi9a>!Z%WX>GyL{(<|+SK-W)CEb~LUjHtFGk@7A zaneupM@!V%2+lkm;EeA9=YD|KM_aHSFHc^oEq5ih7shXkiN64K7Dpb=hil+mzt!QK zC;VJYZS=o0;`u%g&&N1VMk1c`WG0;RVI}-+j5h=3!#nWH;r#u8y)hpep#J(;@AMzx zoIkH%J<@-P@$1jA0Yrbz_^L@YL_d*NLOqRxN97hx`oG2@Z*RnJ$9R{*+hM&&_r9W^ z=%3#J{}s-8n?7kD75zldD-Ob2?;(f|2>;N-`vxO@z#@g|NWbd z#j}L?R>7nHd=LF80^bR*3um1x;JXl?7xU`6q#pY99XQ9^D8{+}c^b>DivFyH7lOZ!@m7Fyxm+)+kcZD5*1)rcJW)HM=TQFR z*DsMr_ig+qG5n9n=fjJ^`F*f{KQoHw_rX>~JiiaNCj0~BZvfu|ZwqJro#FEk-xK}> zd6Ntfv9;Jc{Kuhd&Ny{cYi_{|0y>@{EDAevXUvb6gdXCvIFH zBR|KrAKn&uSbt~uXvFt~kA+WxGtW%;Cy1X1{}jFiJ_^1Xejhw=@;q#rzUs zpnrxuT#s$wo-dkj_repApX;j_oa>A0F>Zaao(9M>9LsGE9|33mRpG3^3Oo^cZiBOa zejhvQKZy8>$n!az^|Kz<-y895k*6EHnEd=6b>@%z9_+aKkHqBX_Qm{XTmLsP`T4!{%zw7^AC1Y+_0IffTmQE) z`T2Vsm_M%m_mZw7e12!dd^m>u{`b**=KA${6`h}-!g*b(kSFr*lJfX@HShoPe)TPg z=lNs~IN!4^3h$5nzTBis>*VuBU#@Rokq<_E9pvGAvpiqr`?2j1&pK1nhwri6f1(f9 zBR~5Powxi|AEM*C`~PMij$^t1L?6l{Kl>0JH+{UE57F_+{omCG-p`49-ui#>`9*5R z)eQaQbD8M;&HK#fGITzdp+AD{?w@#$d@1sCeU*lnMg0|mNBfiL{K3cN_rukD#>7uV zevXUx!@D8>TEz4D_)Bo^mjWlBCq%ado~r3$e@6TBACmI>PloV6k`4(8Rnxg9B%BYg zmE=DiFt|{>>f2GqgaqGjM|q<7?+Zsqf`o+J$^SngA@Ukg{;-Ua@S4FQ^5>79C(mt` zzXsx?{L6M2Tq{2IYr7HBT71?a^G@R3JDA@seqDIc_;qi$5-2yM*~^@pP|QKmBt_-sh=>ExxGzb@KX(`uyHEmY|gQ zh4n1npNn~(&rh3ImH4&cfmki^C9AFfjm1l?Hn>5&(>XS;`iqyYVsMZ6qwiY%tD4x3W(=^*&uAj|C1-(R?B~l#Fxon z?)y^jL&c`H+(r`r`FM+OBVM?M^|OokV}lKD6aRLLJr>VH%`$1(FK#rO0wSR+1gpT)l<-mIwAzfXM5Jo6*s(?a5t;%&omBn>z};zj?o#Mg+|2pdpc@pHmFX(^uPORN88@vPIV4gkJWityl?m-_Fu(MrM37>;W?ep|7RAN z7Z$&usMTLid{a1p*Ae%A`g1_f@BQp6@qc`4>vw{9@n@`_1>(mlnExt1^DC<}eK=9m z<>nE8@xw5$#J&Eq;-%iU{?`^C7S3B*h$lW{^>h}mG}G$8UA)=(mVdsuk9UQ5pD>@( zC*50!etf(qTUh>!#l6nU#eG~?iy!J@^+fMTFu#whxwwz(CUGCvByq2Qo_Nmi;_#c| zzFs~M_j&b|xaavnylpAlAo7G8I^H+;=ywKjyhoSXe>aWs8^sSjXzM+C*3Ud%|6Sr< z|5$O)Gfn*T)wW*dihKT*;-3E{anG|&yxlyTKYPUUJ!j+kN_=ZMtLGPS&yzN~;7j`P zKF{4`@mIxo74bJFSbX#@G4pf`2ZS5MyFX=h_7V3yL&VqAw)|toGlc!p4DpArvixhs zCtI3?SH(B>v%h#xy!Sok(RXHYTwc#f@n+d2%INgc$;nSr^Oe~xBh0ylCsaf-CZue>^kd1X>s4a zYKZ%MXe#dejgI2px7)-o3fGT!i#Ka(^-K_NyvfEhOMGPo>%$W90byRP7ta>HNa-DM z@8?J2Kb5h1eiP4<%{=D?Df^s|$F|3Y;vK>T-<{&wvfI3UTKxTcEbj*K&fyE6Hj8fx zztHKR_-m^z&k^xHQ_T}XpL~1i-QDWBM7-zM7JsF9`7P$>XR|*&Plt-upX}m(U$KDr z?79|TLcCH}Tfa5LyN4I6uM_`hfaPf|eqne~w~KhyoEASM#vc`*^p5rCE%D;NTb&2Q zz0PmMz0P06z0R~3rtGKJnJ31pihG^6i4U$5#w-4EL-TvZvxNI^_lqCjVdI@6zO10- zStvd~+{j!i?s@uLoN~O)!+qc(;xn_^_BBTQribm{PZ9qp+*f>9Jj+#9|Fh!r!hY#} z@vMt&y?-a3E!-FSMf}5XgEL3?Ac1ceW$Rj<`NWqkH7_In>_O{iMe(WgEdB=ZGFO;) z68~t1`90!m51Nk=FY>hY=LvD|=Th<2X|2w!;s-Cc{O^iSnQ4ARd{g*^d&k9Vh8u?& za@fD~e$EZ^EsOZ7X;yzJ@o&Nl>6OF_Y_R%kia!_b>$VV|lF{NjiTnJ#Rov(2AaU>K zaPj3eY`)DEKX#w_Ch^0?te%g=eSRJge`3A$@lSD|pBcjWo%eZActDg_+~?+Qxm?`mX9@9JF0l39T)cm{FVsOi&G*)~0pdk!Tb|M4 z9=|}`k83N$@1J7%Ulu?AgpKQ6@fKZd{QJcH`1qB$A0Lm4ANk$tKP8?q%)@hYrR?*# zcdVX^#1G}RJeP`3K5gSFAznE=|Eehd#th4It@!)PZMm(*uME!-dW#Pa$Ctt4v!`1A z`^1afVs%az-@Cz;^ptQ_#@)Y z!*#kp!1n#mv*9`=LwK<5zW;KoC!hHF;lci8;@P{{Jg6oTVJvKlf(!2G+!aUr=I0sE1qe)<=-w|I=}h*;JKfTYlm$y7Q#pi^+RTRHA?0;&AXT93;+$iqxUBu5RVeuoyhlTt3m8 zpNvXK*e8BY7wi8C@fHm%|7r1OLVxq*OF2LH-fsV0Q2g`oB11KCkFP5}u$o<8bQbsc z9^&Q0esZ+9$4?NS9`*xIieEU}>R%!LY`D+4Mf|2V7QaJ$>p1hD#pm5+eLf|=`-H8p zi!Zf*=kwE#7kR`l$ZYXN#6JsP@LVItJI46EG5%zX?~L)2F`hSn%5iy}wZ*f9_cXeQ zzjmGd`<~*9j#wYYiF^Dc@s$g$|0~2jew}!hgSOmV;;X}X%Uk(bs#{kIbuy-xZ!O+#sH|g2i_dzc{=YGFaT>?-k!T*7`Y1d`Ao0FU=D#bG`Wn zagTpR{E_BX=RR?NzIjl5P&hw7CGOWp=@KoU_pNPszJICs$Z&pBNW9Liw!W&1e;D3} zsV823tc|yuxX0fnJ~_NsFi!ma=WV%@#IIkFko>bm{QOe3URH_Uy2t9-CcZt~|9nsU z=p0+_*WzD<7srl?&kfs4#)1jSKi=o%;eCv(;{C%fx+x{@@z;p|9%7H{L5= zd!+SYj`-JQtq+UDYc93AUlaHEx5U?l_r8vZd;D?n{*~=GmF=>W{dw#ut23wg;|s0M z^5Py}P5j{PmZ!V8$M+G>9nP<&ihKM_@#Wzc5v&*Y_?N^_uCs9-6wfpuP4ZtH7Vr6z zdHTy!_Q&rJWERia!QzXHdwgl}99b=IJ8_TiEPh_tF2;y^`~%{{&P|)VfTiLdzefCc zx^&6$?~9MDY2*4>{M2--KTRR~)3+~=&nUjHkkxagxW|_j|Fo0EcM>rAL1ULzDUYGG@fViSBram zCGkv|(kCalS={4$iFdDO%X>uJcU)0*NH!ue`_@qKSw{x0JFT)wAxuW&zYlz5Km)}Q;u zKN)KIpAh%^^Gn6okF#;@68HGM;`4{w{5dV|@#mCC*|+z@3-86nJ-)Q~lF*1 z`QmeWnU@y#_zL0^M_T^Q;vU~a{JQqmw+F;Mewz5CnznwQ6|dCOmiwak^&2ezXW|}z zNIj#C_rfdf-+6yLK9~6Rb{1b%+~ezrPYCzPdx*b3#p>@XJ}{?^cbd4z&l1lbo?E{v z?(tj2Pp`84-->(uPvYsrbziQMDf@HpotCG7_`{2ATy?}f{yOo?4_H43h?HYkDA{s?sVAnwmMXNmjs%~j(5d~>6?Ki}Lc?$0;( zi2MEO{o>!=Ve{&cxIf=KCjRYi+m14pNx6Rg`Q`=UzlZ0)#l-#jW-0Nitt@|Caeuyf zop_gJ7T;OipKo>-Z`aetJ5t=AZ;li1*~aqE7x(9zi^abR_f_5!_vf2C#d8m{?ew^~ zKi@ndK0N$F#f!rGCVrma&o^_6e|Mvex16{?->fYD+Z?N>mAF6OY%e}9Jl`26?$0Yn zi|6$FgyJ5*NPN_THqTxc_vf2$i*E~`H~CuJpKl%$ANa0~H&fY^^Vy$oW)uHtob~ex zaeuyfwfK3jSbRfqf4lExs+h&)-ShpC@(`zx6(=W2Csp zj~DN7ztyu)+~b#t?`vS|>rHWw-!A@ZWm{iI#Qpi^aq((l|9pP9UiaJ$|+L@EKu#iu?1;o#N+qv-x>c+@Ej$D1Km@_2+_0Df{ftH*<*J^rOXH zA@0vNuNKcV!QvZ>`}4|{;)TQKDEo_h{1EYn-mv_0#D5C!HEkBJlF8QZL2-Zncv!qw zn9mt2r|gf%XBFSD(Bevod;B%xuYO|vZzb-}2iuF^@qyJpRNUi7igya<{Y%9?evSAg z;XSnX#XbIG@iC9seEVJ86k z;uRNK{Nv&tzfk;#E3N-q#65n8_>5O=yvM{n{%7%TeztmYS54VBe}0!JerpqpuP5&D zjm4iFWbysPJ${h*li~i}B5{vjE?zc#ZtHz8ZuOM? z@%RhGpD$!_wZuKXf%x@xE&eWXkH1I!*YG^|NpX)~A-=A#)xS^N;}42&{=&Ae^J@I{ zcrOw!_p|lCrnu*?FP^oL#rG5U_(9@J!{=KUiF^EV@yg-(^`}57C;*GycNd7s$ zmi_7H!~T5pBJoed7u8%X?$0+XiEle%d2bf?=bOF6hZVQ^Fh<;;Z$2PC`B}@qNZg-q zE*EbT*6$nQ{(SQt@sfEg|JUOFJn@+L1J$hmIculvr^n|PKQO}LYKwb(L-B<0eqA4N zj~^&rEIc2aDelh`=Zatcsr7%exW{i3zqWhY=5_(55#-^VflX(_veXe!v5a3 zyQaI-B-dY9+~cnlZ`Leba(ruXkMAHpIIqQz5cl|T;`2VRdX|a%^TemcOJ8B*{XpE~ z_lqx_V)GzFc<;vh;PF|+C!BBfml5~)isHq>_fT~Z_veXS#UIUT;~gjN@sq@deQe`h zFYfU#iB~#c@dw2{{;+tS*Q}l_*IJ*vKmL3(yLiKJ-?gH+KOgkZ*?6A0;r+l)G4b8R z-~G<&nI!J{XNWHvYw=seJ${Gy;PSS9kBNKy&*HPoSwHjFPuU-jFDyPTJm0@T+@B|Q z7We0gy~O=_Vt;YZbGNwX86)m_ri*U~=Owem7yfGFT_`>>yoa`0{Pg+hlND!%JSTkjbfq+Bm=hW%%D@z=wBr_$nMpR_#H#Qk|+ z6Y;g#ZFwEVv%F^Ws*iZOb{2n+c(?4aLihxq+r`!6J3vAX3iEB^at>svkXjbYxl7T;FF;=76ae7H^g zy{1<8X7Os_`)Rj{H+snG{7l^Ut0!YTZ+LGdbJF6X_wGEtQjB+w@p0m{!{?F~iTik$ ziH{2J8EzB5w6)EXcf}Wl`EW%1=Qh^o@5Mh3-+Pd?Ny_=qH@qK}Lp*IbPb(*WUpQV= z5g!%a`)V$JQ$efe2Jy|s&2JX>{*MyR-`m#j{o+d}n@<&AQp?6UQ~b$reL7Ek&9@f6 zSbTTb&%Y@C&U&l=HSy88Y`gnOyhmp9^kH86e4851e=ZRJIUG-Oiu-m{M7(Ei>qB{Q z&(lo2cKCjt$HW_l_adGY_w%Av;(lKAym(kG39pMk*VX3pTjEy~u>R~6pSaP+^@;c| zZ<-$!|80T!3GwGQ*!n%ES<3l8a*EY+vG}(ke?jps;rjGy@#iO4o{HiZ&9Zu$h~Jb5dS269`FTme{b+L zasR%iPsC5uwDtalc>VBs^JC(k|Ae^bzp#1A_1iaWcbAI$dwo}kXUS^+zOuOI=@8=s z#aD&n@=)=`;ePBx;(lD1Ek3%F&8z3dJ${q;17BGD=i+``I4u6cg*HDkwn*8x4dHy^ z0`YIZw)m3bUBmlMWyQCawfK7C^}_c{v=;yVORK+&c#nsyzT3oK8Ex}+xcCQ|EPkB$ zmEjkcP7yC1zRzKnxaVIc?)le=d;S;2J^!2H?LM*kKNk1-c|^SSRW`1Z;+`k(^(oh5 zrEveJpm?EQtj`t12Zrm@YT|_wY(2IV&v2}T56R_Ddy#b39$tHnpOwfKtSwR2nl z+lpU#%Dj)bzxO*>{8S~|e~uRS_kJgfd;Y~SzEymDxK7(4UZ9ZGd04z;_+0aM;-|y+ zfoE!!vY#HGRs6mXUrPMr^48CC;=kN!^)wat_*UX|Li_-6f3IMO_}=h2{h8ulhkE9S z4-d!37saQAer^^ozr*T3DE?T8KP*1|cZ<*1I%Ploy^gHn$F8&O_bTx_!+UY{#C^WC z5cl`YJBs@}>?Q8+ncpSu%bgtKPsjMX;yyq3h~E=Fr*K@{=i9I1uZ_2Pby1s?{q*?U z;x~r)isC-sYKXrR?mM*;_xR4@mk+Y_b+5S3&#~e=cUb+4#C?7)7jGT*^KXg!{M;$N zGn3VGT-@j9uj1c__g-?|kg}gXKl6+G`$N^me_L(y{5o+zA80M^^RTnH&*$Fa(*|1K z2FCbs@$_>neuB84Cp;$Z=Lw6%{XAi%xSuDi7x(;I#XbK{anHX`-1C1aUSfo;-`~Wy zwl>eyHsyMJC)@|iF7E54fVi)h65_sI%8UEwO`68|Z81Jc{G8ra_e0`eEVT8wQr!0^ z>%@LQ`&I`i*Y`;I?@!7@ah4`}KzCWoXUU91B zZz=Ba?ZjJ8vG~E_zJC}l-nohO^Ko(CUp*myV5Q}MRowR{Tf|F-?euGL-@hFbKmC#A z&l39N{q+4$cJXR2+dRKo-1iSvV*EPs!_BM@ZNz=M=pydh#ckrgT?`WUdPcMc265k?Y!>(Y?~8l>PsBa{*W#Z4xOmp-wth3Tw?BRT`u-}1 zxbLqL#eKb8A@1v?ytuEI+Ty;yx-rHF$M|e<-(SrWKYFE|=Wh`A{ng9jRZrS_-z)C> zs{`V9e_?(6P2BfC3E?@9_qj^g@8uEq_(bu~uCeW+hPdy4>WS}bXYn_Qdwe(X2_b%r zxbLqfh?l?J#`~1G@2^&gw;gQtY!~EDDK;1K5@TJDJt&Q#aD~_bxJjH|2%91ao^rsiu>n(JBj<}d2bcp`m2p=RE#f* z@m(?gi})F;#QpO%Q^nI1Nl5-#Chnh?d0M(KbzT9pl9pUTpO(6@NK=PGN`mCE@wkG4Y}M(R@Au9W_xG{qimyMKF1hdx;{JKGSHwFuxBB;p|1s0X z|B3jUPozu!i$BE=jk5T2Zm~bTZ^y&)jw0d@)V1|eQv5)8uG&&OQ`j%vDBeA6Uw4aN z5UyuOiGLfOBP{9{tBLrqBi5gZ;w{7HCKib23-2?p6W{c# z<=G^@C%oUaTRd0zT)?N|-RoHWKZ#fEZ}a?5@#Eop=CgE9+5bt;+dR)M-ffh{6%fy| z#Jq_3jbGbxe-alg(TA@0|+4~qNs?=11c?X8}9;!_XXdf6cE@vn$q8Q%ZdC+?r; zIw)TEu&u{a;^}tVa?^$T{h5heB&d;#(8k6K)1@hW>PPc89QxZvF0@r}j5YG&~_tA}~gOZ<<=Eq=QAj)CU0#V0SY`drU`}bn~Al|&W<;fZD$NT*MKD=L%U%bc{mcO$2{PmWnmU!uH7T;Ukt@w|JZIJ!z-Kuge_1nEr`=<9ZV~tUw>!j#R<-!U;vWCK`1)|a`ocR>_Ti`S9P?`NcHw?*V{yNK z+fsaPc%P(?xW^9^&rsd^GfCX<-_8&({({xLO5Ee06(1k&PrfVe_e=MP-__Ond0gD@ z5C1AYwSv`iQU8?v^!vlP#jgz4zh%Y!{!(S}rs4a6TZ?xL=Q$n3-w4O4yTvoUZuN~4 zpL?TiU-QL3Z)59aiTIJ7)}Ob=OUZ4o3+m#4CjFjX5ozYoq1KGazL@J-(p$ zkkJ-bTioyOH59M7-tylf?(x0F7lik&#)^CVMDfx0Sl^b5d;D7QmEA($#65nm_(MIc z|G$ZQe42qN`_?i%|0*c%_a}>qSKev$R~Ps1PpBu}IZNoLxX1SvzvX+&KS6v~_}tJ` z@idRxcvp)T8fkgfi}(M->e(mm@dw2xgwNxoxie+o@@=;N&M00od|y*hagQ%0{z!t= z*+l%doVH=K65qbS>K`EP@k7Pug!}EY#K$(WJoCh-+-LPXFFqu^SNy8D-w%09+&`bc zTRi7umVdvv-@pAz+?V^ExG(otabIqlyHc(%Uv6e`Uv75s3$C*MCyM)hi7UiUhxcPD ziTm^My5jzvy_xu-d#&yp#r?iSckzo}wtfze@yEpdeU$~`Ys2-PMkQ5T5&e9JBF z^R2LW!EpSl7US(>{2uYeHErIG7M~uzSN3snpSKIevxg5lz9jDR_I2?U;d=5@ai51@ ziQl){`j{{zWj{UsT=5G+d=YVNv*Y7Tai6zy z#SdL%@$ZVi5#E>jK>b3S&!35ZG{e^Kx8nXB}@ar}&7P_V4?O z_b6=j3>1IsF7pxM?Mhjm2gU2xw*EXS?)RUc6z>=A^Q;l~`_dc5%Y^T5c~ji)Gw&21 z5uTrYDDK<)=i+|<`Ixxhw?8TF_odU{opQbSed+$7?^u0%#XbHr@tonlYuaHc$5p9{9j7iAul}LcQ%&5jTkDD+3!l^PB<}Iu z#LsJL^Xgu4ziu5XULc%T&lC6f#p1aZ+Bjbk_v_p(;`tu7_=DnpoqJgP{B+izboZp} zr(fr07JqY{ZFhyl{k@bYci%Kmu#rQ%g*Sv^(7J-&{3(?_ijUB&&r!L8!i!sjFI6Zh-B z2gT2S(CS_w?!Ra8De)GCtp3g7Tf_CyHu0t3TYtU~_v^%O#Gm-e@@Ed`%YNU|<1Z9H z5&B%@-Yg~NT|Vd5S?TKuE%d;J!O`*q?|;w_I@|F?*H{0{L& z;eDQC;(nd@vv{8kmOuLl`_udB@p;8p*2h{By)-J!j)wALDz)KWky} zC&l-@X!R$Iw!injJ&<4xO%(s~P}=0cqT5>~z;J%c7@bly% z;-kX%($p09`1<1eCRyH|;*Yd8zhAt5FRT9vaX(L9D*noOwjI4D?(uJlF9`3UeJSqe z$w$R!jI{n_7@M*`9-l?L(j`_;QE@*{E+sy`ro}f9_w(dt;&YE!9lgZ;{r`UAQ}S8- z1aUvlpDKP{W2H2-7rv*ox46gm7cbM# z#yeizud^nLZw%MDYsEc&gZS#u|4+sJ^9WywFP>rjIVJAbS?TUi+2?L$tp3ZyJ-)d3 z#SLwKHWByF`?M1OBHVWxDDL0ybhr4@rj~!IxL?Q36dxJhBV8$;|2xa`jQ9ih+I;&| z+}|VpO1$4y7N2%P%Dz2*zxB<3e~zF3bjoAPEiCbeM%ll=QoO{omcNO(e}18r`11Ld zXQ;S;eqp5eJw>ga1>*ksg{Q;|oR>a%0o%p>^9%2*@3Q#?$UwkxcjX5xOm)=}KA*LsWl z_1aKz&p$23SBV#W!RmQN{NeA+-xbe%%;w)=ai3Qw#s3KB$>}GioVR}6cagZChvyeR z)!O=BNc>vMH+kFP6UFMKa(CviW|zeT*_KI_A9@d|gDKOE!F#rXR%enNcHwKm=y z;e6TWn_nm975DX2S=_G^Yl^>o($+_3@nPZjsCF0M6~5nfg}Cp3HpTdM@l%)D{&2T= znqsydKNWv8><5mBx6EyMei8TQN9n_PocGP2A6+EwpQFhy?$4FV$9P-uM;h9ExKrHo zY!JWudRxEmiu?ZaP>g4ul5#up{by0}vFBM_S#jU*RTuaDSVQq@!)?8^6ZiO$;yDtn z508lZxK_pZd*VK>G*eTKH&YG!?@Pq}b2^2@_gi>E$r!IHUUG%4mxkj0Ii1ep{yCl7 z#r<7Pwp4@_ZDV|`{#G&i~I3tg}C33 zdS2Y`N4+lY_nqDo_xn_zi2LVpz7)@v!S;K9ihF#9=_%Lmo_#i-6UF^_S5$oPbc?Sg z?w{XjAbvskKBcbW{`s9-#Y&uto9)DE4a&e14H(Y1?@!CI+bAkBE z>ekQV;vQdGeDo=+zmd3qKIMAxEbXlSJ;nX=DYuJv9%1qKiTmeq9u)8YuEj49_xPv8 zTO7CgH;Mb_ao!L=cdq6CSlr`37ysy2>;Fk{?@vN_&hP7`cKH71OT@iDmx>R&#p*9B z?w`l0EdFUWtG~Ip$KN2nGri5{KH~m)oPpv87TS0xh#k z#Q0)y|NPDy;{N>Q9r0HeS^Y=F{k@1E#lH^ke`cALa=iXLCA)aW@OhBw!+qL8;`_q$psC{iJY}YMt8g9rw7ADVFMe^jAG=H3pQr2bgg?(x5h z4|&h($@N&uetLWX@uPKYe^Nu-svQ*zc0~G z+&^bAT-=|J+%N9;!yo#8blr2*=18>f@waW;)3$Bfwr$(CZM%Egwr$(yG^c&fnO(oL zR=(?I{+ZRE-d(9wc9Kd}B@bNhQ_P2JTw*m`@9!M)@dt3d2k{L4aA{G?<7BjD{o)G&$;=~APWQj`%lkD%G=QJY3_ZBByi*AnyZF{{u9Ch8J`FfsJtG?GE@2_xyMVuDpE=&oemCe-(Z}8!jUkktQ)>mwT7w>HQwF6#q zPT>D4dIYZbcP_y7{?2{4#-Cro_5RKmxW=Uex$CalS?}+Jg=?HS23+s&#DnX6PXX8X zb7r{4?eoDkE?p9?ap`SvJ?HL)M@SU-zjnR@*EsWIcxbm?_cvV6t-+Rf^RsRjD?b5T z@yXzoA_w`efa37!J1kFHz{hN~@(027+&U5-KAzQYFnw@xNGT+g}b;7yBIdzOIfIk!B#*D0%iOSsknc7P9X z-_@A~&*Xj|a36eKLu>y>aIO1#2~SYe>L1=+ztuj9j|Ol5zXAXAUrxB5vkJg7xV)+j zS9~M*x9E1f2Er9T0$${x)qe$C;|A;CtKGWUlW;xvU4YNcX7zan*ErQ%c$%UXA9A_1 zliE}7??ix)xo!1N3Df5K3x6t)^PR1`@pq6WCUE##Z%x~AF=?he)}4@ z`sdr>>YpEms~>(Iu73C(xYm0-h9BB#$L}{>@xj)5k8cJyewqNTetRhAaLRe8*>t55CUZo?7n_4*ue!#if8NK0Um@`))%i zxYj>Zgr^9w_G}K<`iFM#@oxRl5V+QRjE4UxX7yhPSNsZi?-bTPd*NE|aRlBynB5<5 z!4>}yo_mXx|1Vta^9LTTrPV*$dhhX4`^1G;cHc|M1lM|xobX1;tp4TUimwKL+QiPs zHgK)?=nT*G)8a?M6+Z#KF{0IH8C>f_*1|vcwRX7%*ZPpV@X{NtJ|Q=F+f(a9BEZvs zvE!8@+-i2)mxVg6p~a1H8r?+t09@ zy!)$huqg0)gRT6uaK&eV4`^@kRpCeTTDx_FpK11J{(HFMzrydi^`bGhdfQX+@!|8`ct<|C;)}wY_p$bA3fDMc8~748ZaE09 zak-K3csVQ|R=^d%4t}+@<>y(r#__Jeuiv$H`2^Rv+z1XBNfopxpV|drX)-J!` z8kY;c-P>*&KZyX>I*picjpHSRYaA~XT-(hI*LL&3wcVm{ZMPg;+pPg#S=I8S30&h6 z?ctio?+e#F{s_3{@h8JIUq277afwxMtq(cqyhF5j@Iux$>(ePjHy08kadG_`29f2($F2gm? zeiQ!1y)PWbjmM~8QDLo>69cZiN(5J4WrQoQ^1zi>#o-!{ssvZQ)rBkHTEewHWT21F z_wfU8tq(Z{kLA9b_W-WEeGYG4+445%EMIfr0(~#iog|L8a|_t z-7i|fm4_YS?-E;mM#B|93BJO`Z-6Urx5HbuxAwUWSKdB?k9WV{8g;j~J->XmKgWjG zs%!b26yDj*H)Vut{v|(L^DpJ#njdNA<7?op@>zX0!jI>$`{s6dtVDLa4#TxRwHfR*Z6ZLxW?`C!Zj{k0rf_o}+U^<3E-{(8IBe->QNi3{Ol@7aFthb#UVJVs3`|0!J0iErT3dRqBm z4|>~E@loI-{sj6jFcVzQi8TuPk5nS7C3)gnL`S<{M&tA6OF>q~n zI$Yab1lM*~`}h`k#^^!*Yv==TZTB=>+r0+YcJKT6OZc5=c6`6UwcS8R?C*75)po-_;o&*nMYd99-Y; zS`OFo-3Hh9yAHy&Zs$B)&ndUz`X1Lqc)dE7Z$IIR5A4<#D9@`Vuy&6N*Kk<_!#(K-R!(r2-oxM8ugmni#I{MW=#y*=6-F0#|%#_|-91pQdnqU%Cx^jr(22 z;c$JQc^o|LBiqjEn|w)%~L|C(Vw9=&w1NT-&+m?uXokjCkMz}btH1OVuKv;oxSq2@pZB)EJPlmWSta2c+`6Bta6M-= zfa^J{FTDIL%eRqmJqOK$>p5!;T+dlM;d;(G0ay7CeEc_D&sjk)c-w95537FyxSq3e zz;%2}!1bI}8LsE7hH&*i+rstS)EU0ly`MW4uK3CD>(wo9*TVIjwFw^jl(oYdxSq3~ z_;`qm-u6^{5+5%H*K<}AxSq3G!MnP7rIBzwXN`wPb>sZ&;Cjy50-w6x+U+M?*OTy< zy!$JU2OqK5?#r3rdd|uV|G&I~>$*`HuIolUxUL&5;d;*M0@rg^f4H8rM#1%*H5IPs ztOao8`5L&Mvkv?CGarw3+1vgqCkI^5S=Hfs&Z-N)m(h+_AGn^g2E+4SvwAFs>$zza zyvsl<|1ezfr{IlpS^2Nw<=p)s+!b#-q&#EgCx`2~DIGk_0E;gHSA2PR+)1{*mT)~c zb$}0a>wZVU6+aPP{hQTiHC)eG8{wVZeDrC!p0h5&U%2mTzJcpG>k~YI)=^ybwzHnI z;=mI>v-)R+>p3eAyoFoOPz|o^bEPgIr@k`+SzFGVsxSq34 z!ZW+~onONT=CpDmx$`6R|1{tKuE*|E+3qhH;CgP#4)5>YBd7>hd<}S*+_v3La6LEm zgimtMrIX=`p9MeH*6P0*uIHv*@az+D_=wh4eto#&o53R=uzHM!>$zznyg)wN-}P|CZ-rk!Y4JDVdd_+P z|1!+#^AoP;tROeM?e?IMoxic*dd~U_9?Fg97KH0Lt2n&qF{^(IxSq4x!!s|p_^EI` zXU&0kYh%Z24_wb#hv7%udjv1wdd_+eFPqKEk9yPFZtDLe^YIMuGo!7Yv%&8Sw{i=@ z^H#L@GVopt%^SkiziIXl)xVknSO01;T>Y!R;p$)QfUAFX7_R=+ zIk@^)x8Uj*ef06@x4g$u@kM;RIb8j#VQ}@Y#=v*iu>4sKSO01wJo!$`|BG<-mu|qn zT(j~&!WI7=KL3F2e;hYIulrQZeU?{w;Q8Elt*gP+U#bhwn$*hg4p)3Xc(0sxeVzeV ze`!9v!Ub!e9dO0(hc`)T?Q;{Z{?!9`)NU641Frs6;5**@xlzvIcu;qaiVY`Y8L>MyN;H!g4W zKL}U+3HapaR{kTn`b#h28QprVpzi-Ve-$4F{&|U&pA@eCRT_A$h?YOa;p$(NgGY7i zOPj#eUup$^JHpz399;2J;S-x!{ddCEU)m4R-)+uXVr2eHgC()hYPV z90C9R_ZqJL)kpa7DOR7D5A5HmJ=MQT06&<_+NUsF{i~`zULW44f|b(+uKrJdxcWb% z;OhTOg{%Lw5U%m(9X@^wu5syq;Z2@ey9IsdZ8wceM}TWwIt@HgD*N|2;2JkB3)i@G zZMepzTf#Li-2<-jC;0eUxW=V7!7ID>wa>yeF8vIy4c5ap@?Jz3rxP z=~(b%Zd@)0T;tOD;J4g+p!MJymu>=o)7I*-8m{ZZ9v?pqzv0GVF2Y}BxAO16rUxn-X^AY~>dEo!b z{{z?cC-hVAe(CxX4en0EfTVE6mxZr&^Q?{G+OOU|J{PY2Is>mg+S=_QT;ElD4|mA2!4F zUA6OYeOK)UT;ElD4A=AfXSlwr7WlchJ#~GK4A*<63E=v!S{k_CYs&%GI7vyk?(bFM zdY`l*T;Ek|3)g+5CtTwsL*W`HnF!Z-$XvL_PgcS8owN<`lw~acPr(&`5q|Ni#lME@ zKJ^j)Z+km_;a+%;qrR&a6<*AJ*C;()-&M;7PZ{6pQwgr`s?~(&cxv%I;rg!H0QkzZ zcHNr;*LT$x!z0EG`rnQog6lhJC*ebPT790t75^H(bhyQbcd>44M@K*2faD69j8vNNF+usdv#czi{+-vo@1lM=c zZo-Rvw(>v275@`{#ohm6yz;icz8e-F{<5x>p9QY(hUJDo>1pv5;rdQm4ft&L9(Oyq z;=96wT(tHX4cB+lCc&>4vHe^DSNuBo<$tXHN8oCo)9`<`S$;l*t9@R;BL}wn|AFf} zX~AE6k4yCA79SU`_{8vw1*|?f;rdQm0rOlksoeeJ23+I+_vt6B{O@$Pjv~-IZ#%TjXzh~-{@}EocZK0K z_S(O%3)lF66ZoJ_R-b-w#SewAUtq^~K3wDf%is;&@4)VdEB+XK*Dc$x2XKwIKZj3R zWBVKUy|>*ozYq$(FO#)rVz}lPQo+BbwsMQWH9lDyKJAdzzZqQLRcj01^~uT~1J`%e zCc}IFw)l;3eOGM<{Lc%k&mFkFtM(XPEvU6m$bY=;sqdskfCqQ|(bRCoXM%5@Vfj-T z{_v4)uNHjk5zEi6aK-n5XNqLyPlqdh9=zcKYo9%E#UF-OFKP983|IUs_*wT|;xHe) z?Wy?4@Zl{iE)!hi+d1K3hFX2f!}UIUHF%=!R(@Bw;`_jVr?PyQ4cGhci{NqG{QUvA z-e*4!KjPj;dkt6oNBH|Yc6=j$^tPwoXO9Ih?$!zAfGa*feC0qZzaCugvp0p8T59ze z0$2QKc*;6f{wlb>tF{5Y~T+{r9(UjqiPhYr6sNx)u6= zs`tO^thC)waBVj-T-%KU*LIV_FITbiG&Q_VS8LCV@G5`Vd66An@h@x7LhwH~teg_? z2BFN$!S5Ha`c#3R&u!&5fa|+JZQ%MYP;a=#PlmzuU7(3@jjPOo>$^b9;Tk8|2-kOk zw!<}katN;Rle2J*JKcb5T;(xb<0_RtTl*=m)K9AkAJ)u{OAollN&3Ujy5B>e30FUD z0X*6!D}N_k@dw}|7g|0%gokzC84L2oyI&dH@7lzJtKXFb-qBr$^T8Eg6y9f?ZLdCD z{jO&47Bwt>09^6I;bq)+4j01JPg?=cAH~W)2vX|daJ|Pq2(IU>k?=l= zt^CDseHUmIJXQ&-|6#cLIj7+DT3dU*ge(3Z_|%eCe#CFy_Ef(p2E0oGtA94Q`Z;;w z@7;He>cAD>7@n%H)ngD`{hX2T)h(_5E8vP>2d^B%%0CNNKj#X(VnHka6I}5>;1APU zKQs1sZ+q&yK-u8xhm?S;Ur`aRenl;~%4q{vIbGo@X9#@e6U(1jaLuD_^zqAZ&7%eV z;cbV3ZXHrAxaQH4!_^wZ~fh%fK~{))=mNv`%o%qYZ>>9&I9A^JuGl{0v<4 zXqVwP&s)B|f@>Zv#7}Q~Y91{jT=Qsg;Oft$fomQuCtUMrCE=P!s|MFRT4T8Sf$iby z?+t)!9&HR<^Jp{Rnnzm#SO0K5T>Ze^aP*NR{lu1=Fuj=L%Dg7^>EFj zZG+dEY3*|fu6eYZ@J-q6e)Ju#d9grloJswJav`k#ap8(j3}5ry>XQ$yd9kAKiho=A z4d9Az4&U(D;s?PsFE$ch-_7eSfh&GByj&w|pQCWii=Cl=xA^Duq*l*&@a*#~KJ*{^ zd$qIX#UjDWxp9d!aK&eauljA}mxF7bs49HYIE!x$*E~@t_^9Z1d`G}FFE$>2beo+o zOW}%N1Mlj_w-3TKFLnZ+I=Iwe4>#xZ3A0c)dQ> zp4s4<7t0IZ%kSovYycO%r!nn#NQzi`*;pBb)sv|R8lhpqhjaLuDNgFkI)8ZFIdIexfgt7 z9gCj=*Lcfpc!OM4&K9`hcf-rN_ZqIkHQsUu9?HE(^A)c6-|#MOydq{$Z+mKdCINiI z6N}3U*Z52Ucy#w(YAv|NXBxt<6td&n8?Nz$LGUK-_hRP4HIKFgp17-(e+aI5w3F~s zZeHmHT=Qt};hWv{JZdm+dukpn4m^Ez%b)yk&5IR-PmW{pjo^xJ2~T~-;zz+Xo-+|1 z&&?yOfh&F!yyy>W&$DpFUx8=ZZ}s^ESNsonMECmwae{l>Q}K!5OM_T{z7SmTCE)`b zTDdLZ8jtD#FJ95&hru=eGZtQ`mbK3sxZ*d#Z@cTyMYzU`Zor@HwDSLjYy9UAJe6Co zlQ@L8Jr$n{J~x!LXGyrme=5M64Y%Xl90w6 z{sXw?(VoK_{jlqEppf47(fChj_#LZGKoq#*L>L}xaP&~!Zl9v08*SPu-_$&9_xqEPpt2~7tt!KwKAhh?qQ$H;P ze4!hMNdX^H&gxkRuKra?__k}7KaJt)FSUZNN@npx;OZ}ph9@p&`?D0T{?Z!wjj~q$ zQMmd`XW+Bb+x|X-tH1OX-Xn%x&qIarwzKA&BEoy0wzw>C#pi}s&u@8EAFlgvGx(G2 z7C#WK_!02!dn|qpT=ARWryg4ST!QQVeiJ_AvhDACxbDAS;aN9YeWHi;wx{mz@!+A{ zx}!XB#TSO(k8b(U2(J5eOZY$Tz4#Gu#gB)tcE3~bH(dAYE$}y)EzwKc-@o9BPY%EAzQ0inzT>!Uw-H?T)7Eg^AG^SHf9wlaIm6&8XFOcx z%!BVbYx%PTo_fF4e;vG#Tj#$G9wfJwa|FI~o%v{|mzy8V1drj?59feaA87Tj4A1NC`!(Um-Fw+>;LqIeAa{osI&bwH z3)g(yQXfAC*L>V#_=|GZZtvlGU+)K8@889AzdxhI4^kLkFmzZwCq{%Rb!=Jis*HBXlwKD(@42TH;fUjbgEljUtIxcZ+R;Vay8-)Okz z^(MiuuCnXKTDa!*Hp7oxvih8dYhLdf{PBA$|0`VcdcWb1?^yf9j_kb-YhEuQ{9bP> zzaU)mbS2;&-8ffcxZ+#EE4Q=y425f+ZVdePL5p7wSNz}b7uPNR1YGlU=i!Y%Si8J} zEB*s~=~_Ep;i7okQ}cRJ;Ts!TebU1fpABAUmX%)-u6eo|@U^S09-ZNe?*$+H#_BT_ zu6e6D@Jy~BxDl>-s~zwu^Q`{o;F_nq3P1VM>i-(9_>b_{(JVhhMfJA7=IJ8BU%T(_ zCW9+JExdg~E59&Y?NbVVA-uI`1Gw6!IsE8VYoESw&C?BmhjZ_9&4Md_Aw2qND}NhY z^K^URHH%yQFT)jo3m$Qh#s34>yxza?$4{+3iK2Orm*(|S!t3X>_OA@ryk0GMKs$@? z1=qaZKzOk2R*z+H&Fig&HymK~KLOV~-FbM<6!skb9j^F5Zr)q>$MWuXzEZn-!~vp)V0T=RMn-F%VuOXEv1;6p>(@yZ6*_)=bYvafc$ zs>3z@QxD#%la=2CuK51&((e7N1@MP%JmCO5!+5LDEx5*!9>OO#u=@OjD?Ug}?|HE` zljU1HxW=85z^{$8XOr)ys~KB4^7yj~>uDz^?f16=cZ+2J=bSbNrnYhJGr zyz?H*hhcEd(~X7i?P%?}60Z35@VQ@Xe=oo_4t5c|tob7vW)-Tl`(P=Jj5}HLv##uJMzgZk?L$3wl2; z0$k%NvEiEUOA4>p(Ap;hT=Rh0;2J+E2-o;Y8Mwxss>3y|(g?0`mGf}*)2_h-9kzD< z0@panFL?O(cD!P^@BOGf)$fWA9}(H|BnMpa`Qd?cS$j5s=dWo#5dQOp)qgfz{jNpu zAPKFU-EhSpg6FAZ^}hpGzw0sli+g|PH(c?--0!`p-7dQCq9lN;pOy?h#jRH;09QY) zIJ|#RtA9hd`e`lTWw+Y#9R%0=aUGc+aFo{O}OG8z&rG@;~S93n}_P>gn*wPY2_z_D?TlJ_)?26 z16Mz%GW>;GZ{G>7_@3~zU9J4-aP>DfvcRWaFz1}o;Ho0*FWI8 z|At8HZGV05Hws+y9SPvN&!&d!KARn``(|Od?z83Lx-Zv;t3S{jUc8PSm#%P)|M!8n z3u4#ph43i}EkAeq_+1|lk;L1cDkl|O{e%qgOFymt<>C5$glh1;11!E9T>Xl^@NsUu zWjb8_gn97yr>q^e!xg^|zNfG4|9yDWs8&v(q~7+~l-B+n2d;iXBKYo%cD(Yy6<-+M zY_`SMg{z;S-$T&#{CGdBPd}gdq4068{P}S8E0)3ExOJ8L;p$f$gV%KZiU)A@E1tuX z1+()#a58T@>-QHz!jmVl_DKQP_y5zwS8cKQl5oXWfVb&r`PmAt@Bep%myKif9}QRh zBzVEuwx4U@b=>-mP4HZGE&eQg+CuXy@KV*S{;%Nry?_t!&Bd*paLMie$}9a|KveiS z_gs()u6|br`1)#AZWXxVYs1SVvic8zs~FzZ9|5tmSZe{h1 z0Z;tI%1;Z|?=@tBrz~ahRpI)*hT8NJR*yb#t%Dj2f0^3iSHcGjwf0{Re|*~f0$lS` z*Wvlxda6(GuQzSKe!$-cvg=iXRNnSfe=MVq=Z0@{TgenYu(N~c z{;~M@aQ!|-Qh4tfR{#8P^{b1)yT!5i2Jo>xZM!{vd^)_#Ej#X8;TI-ZIlJMP-F*E; z_yxCq{sugT`(2d;>8w1p&;MPoe7pes+a}AaGH~T>E%@{PwqH%*`n{44a9#KMz}vg; zwNCNzjqnj}y~lQVBKJP&Mfitob{wz6M~t)f`T$Ss=7au)=O1MI8#%qVofRJwUU#6y zXNTW*^~nogx!U5Z!xdi_9@)kBfq$-M`#T7pG=-JF4BjrT#jk;9*=6}~2cA2Q`6KxH zGFHwDcuu#z?i0LfD{IGq4BqyLu_-nVWtT((~ zO{?Ebxbkp5e7PH!-T_x0?t|xdzgKk+{xY_;^EY^zebzpI;8SN>e5{P#_WbRhrxL*L zG`6^0aJ6R*xZ15gd|Pv?Pd|8qT~_{3c<`il-=7ZGeSaT3W=|{s6kK_76aH$K<>6Pj z$`8ooZ6A4Pc&hK#p3&i&M@t0PJX%J$=F#%NHIG&tu5r9daLuFDg;#87?b8CTd9-$L zjqmk@YkY4AT;p});TqqY1=o0B$jsh$R{lhQKiX_@>EOCAXN6C4$F)3M<5$(-k3v~K zbbu?qJN&6z_dWyOvYNH?4tQd>zU2~J<5xG~yWIB>KEW0L174%9Z8usLZ+mLID=xgr zB8$%kSA1T0KR3@(9j@`Ndhl#pto$Bujd%5jXN_X#(M-6;yB5IXRkQe=aLuC~fUkA+ zc?JJ9$I6MA)!S|>UH>f$T;nad;c+uq{?vynz8SoM%ePT*jkipM*C=Q8TLV}8CV14H z*8UgaioXG08{EqO2G@8_KsImt{4QnX$AN1+ClS2YVf*(v;F?Fv4?q3Oj!R9r=Fu9! zBm8Cc=>^xk*g$wpH{P@WuK4Bfs|~FDqj1fmoqc=ti_dwcm81QRtK*4+B(DaUfUqJ-fNo( z*L!UX;d*~%F$e@W0)7?{~P~YYURg+dg`)Ej(QPq6Bcg*OmsZ@tHhuz1LO} zuJ_ui!PTE^1XsVYGhE|}{o#7AZ8Ti(wM~atY-stm7_R>0I=K3iyWr|K9)qjjcp0wo zpIh+j!|XVHhAaLj{QNVEkM8CZG)|&^W<2=(wwCAF;Tj*y2k$n-+NUO5<6{lrmrGmu zec+nc9tg|8V`fVsOQmg)f?Br9*WcK#-V>%F$L@XGz|-&cZb z-moS-u$yn~3fFsTecGm;d)Md0q+^Xj&G2H-u>0MO=$RTNbWyo+|JfOD(<~T;md5;RzdC`~jh3mbxJ@9+At^C_?z1Q{#zG#=_XNbby_SAcA;o)PWSX?H!-c!p7zkSo% zzbahub>LHCSbSf&#)XE!V~)1^&xb318GL(vYo7yf#UF?7{A2OY;EI0>&$q(j!x!EWfp4y2@pa%D*J=#kxX zl`|i%`_2X*-w)5d&FXmtuJP^r@c+vzxUL&t;JR)ED(!7IT{ptQHNG7KuJP?eaE)W9 zg=^e92VB>~!f@qzdH4yp-l@5dkMi;DK7I?nZl4{;?{GcW2bA%)+hDi8D*;^ZHzk8F zscq#KgX=lHEIdU)d#-N|SA08ok6l*3@$e>7EU(tXm&LaDlW;w!Ux3e>X63wsEB*s~ zhWpNH*s|Vs({p+hc;P8_JxL2!d=_|vomOr+xSrFi!sG6<`1Wu;r+0&YtYF7$0$lGO zO^3&I&xzaMS9aKT_rlM(alh+ujZ55v?{8!E`34W0&W_6;_=pj<-PmrOh3>yvPm&OR zvwSNson znemYo4H>=NexYqyNg?G4X@qsIN+f(tO;JMs;;_2WT$H)TTaMJd- zGFWnxW-AA!QcJ1eAo@w`$UJ}iQRee82)^a<>5>CKd%27 zrlPk!M;EdEiVPp;en&3{JXBtb&ksNL*6QB?9)5z=r#U>5iys4zy2aur!;{^$?QVt# zeqiyt;9uPJSEii>EoT?wcc8MKe*~M60Z78fvZ0A;i}IHAKwPA=GK!Of~!7f;i}IK zxa#v5uKK+3@t^Qhv8;VUR`%w@8TVWe6@JgnTg8T74Pkkb4zBuShcC16fP!$vmx3$4 zD!k$=t9L`V>faWw`gex+sbUox4p)69z*V1FaK$f%EB0GS^QIY;w-k^_i&XH%#DBR{$9qtXBq}RY`T>b4X$!h!RuVN_zdtbt<1B* zRZeO6NB14b>Tr!aHGpf}sU=+To#2Y^0}tq9c`_M3H;vVQ7JParyKe7*D}Fybi~HWf zU3f<~pZ?6pzrde8wR#4w>OHTuzhU6o->7iK$Ac?AIXqGXt7tyB_O~c}nEO3~CUC{K zhIiUz`!f=*_L=143*n=4TRqppwZB{8+TVR}#UF<&{vy0;70ZVgaP9AV_~L(TejqqvFtbO;wbssqi*L~zX{H6OI>|?m<^9HW_!dJNB1FCzEyW+#Z zx4ZfK7;x1;FdRcxxhWA-v@!{O_gzjtS-Su{r|udjyZK(VgFKOs=Ypqo&o4!NysnRTh5zf` z3m)L(GvKf8+5Rr}@%`{fcdVT+!F#&v><@UEvsQlaTHf<6t6N_b5w7cDEV!abn@U!{sxHN^23})rDhpU`P@a=A$@C^8)`j!ui;40?`Jf*v?o`V10ZS}kY zS2_Q}Z-%sd_zhp{*7Jm{<2^1aCpG-(U~7j=@Z#?GstUj-y7hh~;VQo)JoIZTzX$x) zXsh2!_?PGA>)^L5So`dNYrD7MOIO-)c?8eyzIPh6uD5+=#ZiEaD)4zBG6t>-;1so%Lj!+X52?M8*GoRsiD?zpFi*9d0ivHeO9A9=#sCof$6=d$o) zgRDMP;KeUn`HkRZepvi?`1T{Vzf<8O-8zu@aP8M-c=jt+&MtU{fwtWfaP8L(c%_k6 z&V6{?^yY8j+OIeb?C*74>Swg}ObD;z*5{>%>p13sYkw=j_x82&YtY^MS-s)oZrE`d z2;V-_%9#((c^bN*x1DpxxBZF) zpSaAnn*grko*sU7o3%qW_=7{{Mc^u@3jD+{i?0p8*uv`B60UZb29I>h;^)G@xbNYt zhO0ii-~-}WKj$F4j{Ba;dAREH3tqT`wP%n<-uB;f-u|2re)W{qKRLXmE2lI(yZe2y zitsDjt^D@z%?GWWyTYU8vi%(ozZ%VaDm-Ng+pkUVHP>vrJK*2;+kRbw=WlNDH{dDU z?~{Iok9FU*`vni|#%W_Tw(@j6nH1i(8z0^!s>P*&>o{hE>-@?O*ZEZwJ}if|PXl;i z_g$~4@COI2KJ($~kFA0yC}8m$;5&xf{_cZozh1+4yZ-7&cv&~k8>xx6J+D=^{D}$g zmdv)B4Ib0IhnN?hE2+iThU>Yn5qx!V+inNA+NUR6{nbHm^;f6E3+}W1oC~j+%=|FC zg?s)z2|w?yt2g2EUt9g}!+RaFc6bHP?T+I=@cM3E`zO4;`)+5*rrzUKaJFqXJiMq| zrxX?5>4eoMHhki8D>os$Qh2*QG=V2_^E>_Fi`?(XFN2qLzazO3uJv+z;2KXp4%a%s zOK^=d--T-(;7j->_k0?-nYTUVN#H$$SvwbkH%e$;0zUqcmD?Py__pwxZa{wwyyzyo z&P;;O32nz^EBu~YKeHQt<%QMfHeBn(9>OnFwf*`DkL1RI1H0?GuET?-T3#iB&pmDR zPXQma+UipaKF2*jHiIiqI>MDFec;NI;c(^2B)IZq9$fjb)yJ>Hl_y`|I_^K=?dDs% z#c5&fq4rdKLU=>hUo8Mvo)m+ha`)v{aOFt{cpkSNYyw<)G7X+SgXQ6RxbkExe6w3$ zdKIobxed?l)=7tN>2040mE3g<9`BgNC5In!zk{3wUVpZglh?=V!K?JQd~OBTcDuv1 z-63#ocdU<3hnI2Rqh10p=dKT%;hLx04_E%5hU+}K0ssBW+Vg{tM{@T`<*mM>7!zKj zm|agY!Sx-*obdNOY`c}=`aWkZc!S3l-vzGt-teq0eimHc=UfP1;MP;^f-C+Y{A~ow zlLv6EJADpMpUlpqu&r%B)Sk~WTRBnSyH{J@W`a*DY3-a79>=YJs{w!JzF%4&{&kFP zw;z0tD}N|F&mXJL5_quIR-e`IGK*|K55x7mb_RZ}y_J6zuK0U!#lL_DerVhM0@ryI zyp6a0bsj~A>pY4N*Ljp0uJfpfk2i+vJZc3G=lXj?;5v^+!&C3E{aFgvd9jB6m*wG6 zy34~e@H+`C{xw|Z#YcFS_Lf)S+Irhr@loOR+gf~PxXzjqo(kG@>@NI zz;zythIe{p`Me6Q^JoLSse9kyJY46|HF%-7mgisKI*)$AXUwzuM{nnCPn{PD;5si- zz!jenuK3*Wh;BVZL3on&cD#zi%eZl#%J63Hd(jQxx<9t`@y_s2d92;~!*%~116TP| zeSAK=K|^;PgX_M(9j@&jfor>Gef&DS(pKBA$8hzB-@$eL`3_fqI9Pjcp6EIj5w8Al zT)6tfS$w=2T>arLaP@C{!C$Pf`ptwZem?x}P-~yPaP@}|!$ZBX@}I-iAASq3u-EcA zdar%@cJDsehmCqQS%va<;h~W^5k#0@?-~G zd2$%8JUI_no;>&Q&>g+)sXR#m*Ktn=Z&$(Exh!1qmEk8wSo?H>D^GgBKfC$6IdJ94 zBKY_rwm%2q%9G>pH*THnL%8zfIlSm`yZ(f9>xI=nRGx%~cUfog1>ohTTDz5jD^IG! zl_!nh%9FNm90?H(YrVw7a+6w*Iu^o&>Hu zNd+%a*y8KJ!`(J-0areBhASWX!Icjq;mU_8@RPA^e-^;?eUB}0%^&Uc@#FB1KkU3a z3lB5LwtEY%afVlLjWc|OYkz~d@i66s+AShn;|wW%yaZh14CUb)+@D**HO|lhzJ8+R z;V8Jq879JK9=3c~4Ojd|cx@Md0j_a_>+o~#yComsivI@B;NoNU^ya_D84|!FEwcI- zhHIRm6ueYe%afLHjWcwBFJ5Ey7!TJt!!&rK2Nu5tu5pIl@H;)N{D`qLDy z^RWY5*PlLc-FK$=_*S^?N0;Hczubi98*In%8(i^!;0ME6yTy0w>~uZR{U`~%g!{eY z5^&v*%E2SL@w#?!-H*D!ua2_gH4d)((G>XX>bAd|;kqB~gfBm2@vq^1gWGohg)2{j z^zr7i@+3T5c@hh*JV^pqo@9V4PfGZBE4cDx1YE~`9Q=q|cefU<_)YL|?sq*d!j&i2 z;d`=MUj2kCPXhP#wr9lO_UA-!*30it?-s%ZGW!9l_$61d)#*dzrd9zKjD8px4eqm-`j4= zlSJ_6K`gEc{I~1hHh?QnTEmqm-QdcTfpF!?7`XCe23+~D-p4P(l_&4vI__WKlUmww zk2b*DZi0<~p6RQ#Pq4w>_SExo zY`C766Z?2t_>1dSZf1C+Pqy8h@UeHyi^6rjRDi2}YQxn&&ERUEj&QY4U%1YfsXo39 zuJh#zyir0s?ziBFvRb}P!Fvxw6C;?pOOH#OPH6WlQT<1%9c%txjyxPNc zzI268zhL#(e2D6)^JOaHue;xK-vZb9vJ0LwxYg$kyoZ}N{03J(1RZMsPW4efM1U(F zV#AdWN#PqdTZ?9d>wGB&*ZET3$7{kbyLs*U@Hv-lyG`Nx9kq^doiBahYMX{U-e8>P- zKIDcgABw@14;A4}p4#=HE?nnJC%Dd+-abAQ-r=V0*JyZG_dClI;n4%xbL(8V&X*N% zwa+HF+Gj6Z?Q;UI_PGMr`SQlcBaHAKN1ZQe;mZHa@XPMFSAr|P20ZL6J6_%4I$!$2 z6T07{TnN|svK$`Z-j_TE*ZFb={>(jhJcH|ec>~}0(&`^>q_^F4zC?jvENuBx6rQ?} z{rie=^w>hSDs{quik9sSA{E2YQqcEv-sX{<;g(!sW?{e*>L5_LilPopL+nVJUIpr$ZPxi z4c=?7Z8z9xZ@Vc^BEpp?ap206WN_t4M!51MFI;(2)yKQTl_yi-I_|UKb>`anvJrf=@GW(1yF1{@lf!W3$vL?4EXC0u!u9{z5f#W#fiaP#kN;mVU9aOKHhxbkEiTzN7Rt~^-^S3d0V@q2LP$uGE$ zdyw(o_WXL>{+tM|_!RJiee66c4p*L(g+H5O$Gsz5dD0yot-94`I$U`&7k>PT#czWv zPxins$F$>q2d+GM1mEx8w~98w+iqnt+Mg4`l_zQ7%9HGH>z8{wqt~^N%pYGPTmxe1(D#G*U zv+cEpD^EJY6K=M=od{Q+Ooz9wWAP{8drH`LufUZj_uf^=X%9EyW9rxDo(rfJcFbb~t3Gl}5e!UK^JlO*O;KoaDz?CQW;E_h!`Ths4 zJPGF3)2ZFYy6;gWfGbau!tAu_37oPZv)pI0Vc`^mAJedzyo~(i^ zPqx67CkNollN&z%1Fk%YHN|^g>$oR?7l~(ik`J!!{N%4vG6eN`!H+a%9Bm-oJnjypTPGww0iyn zSDyTYD^Eg9_qLnzBr;ri5)ZCCNeNe;6!h`NaOKHBxQ_d9c$Cgo?`3esuYuRtWAUfp z%99K5f{&~{Kf{$LKj6V@+x0EZ3~zfXPZGkH7O=S7aOFuscq#Wiz=m+;NppDM^H%?v z@J4Q2XenIzupX{_*acTU9EB?%F2I$Cci^i3BY3cub{>6$t3Cg~r!2Dej55>P{`&pF z1aOUqXN8vw;*JZvvHRX*J-EitoBMc2c#;XWU;W@(w>%E6?^n-)Yd!NaxQ@$4xQ_2W zxYjdY_wlcAt!MrX@0{EAE9NY3`)fUO0(iFQcE03`C$@oECsdgj*frunTNqu^T4JQ4oSZ7Y8jTelH(c>Y;EF#7zkJV* z<88Rkuh(#$U;n~&eg&Q5ZGW9#5#c(&;=y%(W%Kc>aGhUu;9qiDdv=5C{OSuo8^zjT zI$Y<=Jot_`wx8SKir)u6{MzF0!ganpffsSVv-1b8_~3KB?c6A)-M^B;b$+FR&v*CZ z3UHlY)!`%D_olkRb$<1Q-c25nSc3hO7Mj@Jeny|1tQcq*nd~xXQl?SNZ?IGrI48et}1G^Sq(wdynt5 zXtuv8;n&^!g9YF-b6cKNhtG4~4j#&VpJW?+xBI=4bMOe=tbVWIS!_U{Xy?Z$6M!>{hJc9;*35ZL?xJc;v%@JOznK^A)VYgusn za~$}n$oBkR0{+T<$G$22r~CflAb9dyw!bss72S93cEaafwf(vUkM8#CE4-vDr<3bP zYy6>KDBEs#_?w01gW#3Y+IGjoL%QwGgMXiA$9F9}U3Y8G-SF+V%um5nB(!$E2@mPM zEH$8*}u;R&+gX2mWMar?XExYN(Zeyo57#C z@7HyK2X1ZU41&jZze6zr{${&0jo* z>-Tg%!aHoS_WTV$T*K-gda3t#MRDI1Nd#~3$>IyZ-+eZ31YeraygxifBJ(-$XjyE3 zcfg;!>)ti^ayQ=c8NSoydAMcX{R-XF%8vsd>AoXc7#_=wr?-L!O=9JYg=bk|$8j^f z?jG|C@G=do9bUkHB)0OyF89_yLx1~oD)_r~=EdQMwp%&v;Wrjoee}IsT|Xzf{=s&{ zcgbhv--JK;Wd0R?aGGs5>I(aNm7mG|&Q3OXGWR|9O7Io?tekf6?^mqdM!}OGvG`^1 z)v0ZN55iBm^#;G;bKP@U*p=S;=V@i-#D@2B-!Do5kMYRrnGJr;eXpqqd|NlGe? zf>urg`0z(ozjpAN*UbCC3%K7083jML+RC2=U!2Fv*$6M>?rWFekKA_^KEVsQ^Df#d zD^K~*#NAH|!Q+p%cCH8i6Wi`D1L48rn9qZ!cfKE<&G|$4eb-M8y4qXM0!_2HS*m=A=X2xa9ghU<3+kH8z{vpl&Af8dVGS9tGj7XQn~W4LugIxfZC zd`)~G&jEi@!S*YkkJo_bnPmH0-^Y8xGe)!W2l)7Wc;F@$zZ)Lk`CWK}3YP!5*V?~R zJ0uxv?N%JVVu5*8__dw3Uyb3B5}J2}cX99O_lIx%YV{clk5b?2Hya+@{f@~>cxtz9 zY8!mqLo5FXyuwK<{}Ozbdyn`5{PJll=NCcO$ERMEL%f=E>oOdsvcs^dr$6NULFdtv(<|glcrFH$fOz>|NEiNbgU-upF%J7>%tUk5idEK~N7x*|gFWDQu zQ- zfv<7vc9y|2#;^mh7GB@2?>Y^i{LJDn!Hbl!`n-W_UgHzIcVOGkDBHdJtN7UPq;C8$ zCtSamT>!o$lGU?5T=C7|Pg7XleuK~aZT0&D54O?D54*!#e_hAoz;zu<4Ig~U@}Y>2 zH}~;TKEA@okNWsyxUOTb;GNv~Pw1WA{nd3Q5`2jJZcJ+U-vg}OGQsagG%o|+mCL*` ze4!if8Ul~$`gLpI!D3oFAMx?$J|1S5cYjq*N*^!o<4t{hFkJ0F3ZCzqwZlrd&a3tC ztpS$LC*i-wSUX&RZ-{IDioW0W{{y_rPODFp-QM;IRoJ$h30`QuT_1A7XJ@c~Ujwe| zQhj*+23Af#_z34i;T_$3@yFqF-TS1Ed_2$|?|$jJ5fWZ`iPa|&T-ULb@W_j;-Acd} zUmm{cla=2N9z2L8wZk%}?T<7Cf_{MU!pI6|DzYSmV z+uAL->tE~nV*OStCmQ^@Tlbg*KEvg0X80cWJ*7hM^6qzXE5iTUV)bbNzxB!L(;i;+ ziN*JWU+iQ)7M>@D`5d_VW2@nP+&YlX2W|UmpB*>t&y(P4=b7+)1ucF%T=Dzhiz8cJ zJ%KkoXn7LmkhebTbJ>2Sg10YXPz3mopmi;*zd`BeP-}LY!jm)#bhi);i z2v>X!c=v|Z{ypH42blMVr*Zx8mGFRLw%zscx$Zi69sC0gSF3VxbEX0;iFuC zGS*S=etmH32XesgxcR31@QK~+-`9gHz9~FwUyJV#SNt$|H#bkZ6dodmm9qxE#Pvf? z!4-cI{=uyucnw$lM|j@Gw%u6A?Ekt>{_1DPF+V)SRXZ*<;i263q8q?3mA7(+!WBOT z9^l5$*T5CO2|lN|)%!a9AD0jJ;Bnk{J3qtAxbJfOg#UPD~j|DF@+Tzl~ zmuInlY&Q6$9u{8_9@dR-)PN`3ZSCI~e*L_ir@i36S6ll}g)4pzyx%P=XE*$yyH6d0 z?|)$RzY7o5+58Fo_!lcb;Dr6X^6i>i=Ntl_rM|@_f@eKz`;`*j@0P`vgr{@wAy$C* zN@wx?;Od_bg%6r&?Y|PP`1SCsVQhcT!4-cM-tn!)e}>1<@3F%7wzGDK?&b~Do`Y)H ze#L{|cKyTb@NJJRJ|FyKRI5)7c#$j?Umsp6jMb+n{8$I`0q~D*o^clZj9X8&5MI-L zS7#Tz%N{!}2jQ9Bc4_u)Y=S~%y-vZvToYkirT=C=KKmXWvH^KFO)=v1CyS86H z;kthXIqPko7%OalGs4eBwsP{q!~eGWSAoxS*U7d%KFi0q`}iIBf%mrE4{(hqe}fO1 zVEYyOoOgfExaWm@aE*Hxg-`!%?NA>cvb1?KdTra@a`>2(R-euA>27_?dAOeIL!9^4 zf5%MQZVdRmGuA%Y;3~hok5BONb@1|To_8yJlbffw2A|^Q>3+f2Z?pQxb>ls{uIhO( zF?_$9S1JV8{j?-JO(ARNws6IFfroSJQYORo+%XG&cDt3oA0E%m%RGj^?PdEL?4tKL zHgxN!Q^VV>vbfst_+{+)_J?acWEebe8r$vyxbB0?;r*Z4b`Qc^p0aW-!S8pp`rLq* zb@#QG@E-2|{sq3$jT;1Z;}FV+Q*JyzK75zEzNLoOifZ*Q;^U2ce5jAF_3@iN9`>^L z_^LjIeZ0Sq@AvWGSN{LySM>2^J|5xf|G%89@Xkvut`uC)xfS87+6>M_lBz-2Ep@&xASx%{M`_%=Rx=!_nq?x@LYkd-JZkG zx$AtC>)!o+oWR;A6I|EZobcH0do^|8if;lR>8^((;Qx=VyMV45e;P1c+}+)!xVyBt z+v4sHi|YbK7kAg?@Ip2 zH$CUq;$y)>T#`QIfZO_zAHG`mgSFun-w57X&!2?7KfIpTxBa^vheU&SI3<1X zh1=)fZ1BDdB!4;hiU;CV;h9=W{q5jw^t?wG_zyj984cf{&lgOB*UBp6@M?Hmy?(I? z{#37joPyiui;M6F$EE&P@KSo6=mY%6YN;oBu=KHN4gna^DoJ>3qI(bO!pFe zo4&W)3ws^j&2_=@O~{~f&Da+%+dcje!$KVREQ{+Mvf zpV5o|;l+Evt^fVtJ@3f+ISp>_6POF1q35@^!Ti8WKMdZtLL;`0KdRpZ)L< zdY=3?+&&LJhuiU3Xg$wu>y>#5FJ9b>xAo#vz4&1-{@sh`)BP3e?Cr((dhv)4J=X`D z-$q{ih!=ke{~B7BODH`)vO4YaU_|)G+p=B9f!pW7#PCD~C4UxpO8p+j{BZjmg$=escOYcLQ3AfLK^WmpoOPwd+1@yhL&)|0a{1#p>k>rW{ z#B+WvJ_-C|Ly7Z;TYMS#i~bVd3U2Wo;bWFaJ!9au9c}jFH@$e6r=Ig=dFsN)ERy|B z3wR;Dp4$%I?TEzpfIqq;^$&zsIUse+hSz;Bd7i>UOp!cq;F;P;p0DuIM`e8*_ri02 zr~AovJr%zEfJ`^!OV9Xgc_dGGc=8-lPgM98J+BfQ{^1YFlMwz`?>|WnKa@`Lr-gS9 z63+y$wO{Ja0e@RU<|`k3rg{;$y-%zoOysTay zX$r5_#So>HjtOoJiuq@JRC{&qMgT#IpT9hu_*F^}L0TFD!XJ!P8`xJU`%H z;z@kyS5lW9SN!-Q9udA$uWLq!-&`p1apCj&NZ!Qo(50pRl<<7tBu{#Hy-Kn^WP$h7 z`?Yex?~Ie_7Jx4;A?^pSuJ@fF~^(@8(8!NcnN9BRW0Wt9192rr&l`p_Ic zeZR!Fg;yCPedq)~wq5G%0blq;^85wQTtxB=f-lg|hr{6k`d)>x@HSN>|77^7+)~d> z__ZS9f$*der4LK!num)1 z&xcZfbh!UB`TcnCo|7a#DZEY;$)5(kP~Yp73Eo>jcjSccZYKE)z|ZcK_0}IAqmuNY z4E%i|si!jhx!!MI6F#M>Ot%5NPk+hZ93Fb1)YA^WeYoW50-vGRTYJMhACf)?z+b$O z>HZC$`$~K)yuV(rp8`)ZUh0_*53BDzSO_mRQQ}v?gLFMx4_|g)`mhb2PS4Nph40tr z=nujF2$uOe37@UUV;A7x7Rz+6!`JKk@$SN-=y}v9@agMheqY1Cj+Oi$;gj?^+#m2l zdVCe;jpufEPLC5J!}AT0xLEM}Ivys3H+?Jhq<}AYEPYE4-xN#cD=U0iYKhMS57SHP zDGV<5Q^_`DiCzuqrb2R>ELTQ-JwFE9C9!NW8Y?+EwN{djlyAJL?5 zf5H0?kvxOpF`7yINcfBl(zgll)cQSW)8U1Jq;K=!3!=-ov;=-JvE*M3-!fL}+ypQC zQu6PFpVQ|H_Q4D)3>JS5Z?;(c9sF%b z$^Ql3FP6lIcq@O~e$A(Y^dUU_wmwH64PK~*#K(m%-y+jZ0w1pTC8mZy((O7Ud`MZT zF9&?Q-hY)JURv)1^n(x5_bio$N7DNTD#4Q!l=Y_uyog@^st>PnO8U?YzFgPyw(xsf zWxhJY%lnG=g2#v|J^;Q`k7tI#L+W@n2L2(9ESGuk87X9b7sC(fasEp9Hyuyb!xQP} zqOI`xnWg>%@FW?fp40G#djHjR_~SpN&S&s5_S`z$;^XM`F_vs;hyAO}9_oY0AU)J}r#C$Ky!TOL- z`y3yBN3XjTgxmFQfA~8+j%^MfIaIcbw(!5Q%KQex>t2=lS_>brMCy+FuV?+0f+bHb z_*H#Bc>(wez5Y@MZqKPTf|trC_4J1y)#H{S@c18Peiy>+y8jAzjS5o#0r-zuGM~rc z?eskfci@k7fBhI9PwyuWr{~*jx!ZD#3NMsg>i2~g)BAk#z+39^ZE?7rmo5iyspnVw z!T0O+#KG{AL#6-I;Ulw2or~Z*Gf3Yyz>l1k_yh2Q%_aUMyqrEaeI0&P=l3amL?T&^ zAK+zm-1`ont>-5reDqwO%XXAJ@!|Nih9`kY7|_{5TurvrTM8mWH> zJh5Kq3WQIsA$4wo@7L*`gr_|t@$cbN8c01MzIgUw^jG;gK0IAd@mBipwtN%#Ngq0R zam#1%Z8ysNE<^mBT~bdFJc&LxdK2!i+uaX%#9@*r^f%A>GEWMxsprGfc=4j}35jKX zOM3A}@CCi4j+S0LjR-f-)~-|##7 z`Ed$7gT9AkA$+0sVLd#%UdP`H@3Bexdkt>&7t#BFZG70G@6Rj;ZyO+aYQXdB=lxdj z_j*3I8+>+lSBm*p}WzN4w+Sp&EFufxaa^FBY} zb<;?lVRd`5zTJ}aK55~WzX*JbUhgXhPkC7KSAjRrAoEohenCI4^?;|%CjA)%PkB)C zOoaD;EFK8A_+4K70^IKZyataKS@M5}PhKaD3l&P{+xj`XuEeK>4~s45qcXv7=zFLt z!@HG}KGcBM=qJwc!`_^HFQK#Sews=Z;bE{tqPoTDZk;hM(9Y%jGKE z;%~#7>vNQ$!+7>*?;rAWba?ZjSs?XM6Eu@PvAv&A$J{wwHZ+eIc6e&&?;*mGv+VeA*i6PgeMryW+Xwq4fM` zGx#IDZq)|<*9KX>)8KIe#OJ`T>gTnsa67-T8{V*#EUzo@NIH&vg(qJx(+wHUbNv}V zTIM$b+;_Lc#etV7DE&+YZ(2_BWQYHiMaGSy@UMElx*~j#-nU;5enPL~w}t!Hm+21j z;)~#aWRm)W;Icy|XQ|tAV`*2&nZ{Z6X%5;6gd-gw!Uhj?uZ{1(wbHJ12mfx=g zxB6>&@h0$&nIunN_!1pAM#97Gl6q#sEzbroegSUhsjk5TA4@&&;k~tQU*L~*9E%;n zv!AxUC4^6SA#u6j7GD4!L-$YB;Y}|~AL_#WBFOgD7oKss#1Djb*YBfQ0AHf#k(R-C zrj-0g;m!KW`u`YyNzbcC)a#Qr9)8l}#)R>AGHELFt_B{0iRk_#--!%WW{88J@VqA_5MEV z=dI!r9}(U#y-e2^Zt+>+@5f7j{(u*lBzfw<>t&Pa_JV(jF8%BePuE%U%z<0}h47yT zCI4Y~c|8w&3O+{9|G$9m)AzBzhwoZ1^BXm?)NB2`r`KoWzz^v1%?e-DN9xQ2&!^|* zs=$M9$aHJL7mt$ubb;IPd@uM;eO_`F+>W;w!1s5OIuF9_`2PgFlC;I=72J;hKfuT8 z_L3lqXFu(DJ~{kkLFq$rc&2!=U6h4aKPmBD;C4LU8$MC5-_3{H@%&PFy_3VS~A2WOLyzsK=WxB=ST@#Dfh38!%)9Vet_)>fXJhOft znFhD`jb8jX-1>7C9{!Nj`5wN#zO07{qIvdb_+^PN2)F%3dARK_>cMS)(GG6=i@tE% zUyOp={$du~_7^MRw!hd3xBbO&xa}{l!)<@@3~u|2Z*bdR#Mg1x#xe8Ua2x*%!V~H9 z1$E&T-xxkf?^hoJxAA-={D+>WT@JVX#aj3yy&v)v-11+5|D)%ZKEZ8&@e@9Jw5*3o z_5JbIH``yNflt=+t3~0qzbFN7rRV1x!)<@j3SLal!wiJm{$e8&C%i%tH z{o@4O_7~^j(-um9KEQ2%@f}`xnZzfL>A79o{vsW`VQ+~m2e8nwzHCG~%T+xYndzA2sbGeum_KHK=29zG|v#FdBJ_*o5}W2DS) zcest8f5G#WllXaX8$Xx8?{t%Tj>2vHJPqHmR`P#>+xYnt-d^wTN*B+wKQ?}5hGz>e z%d0Bf#?RXDd=DjWU$~8*3*k0?ZuH{&;X(SI+w<_F6Qs^yco+TL_b=S?#E9?N2XkL9 zUK$?%rS!io+}_{P30||R#E*m9b=xWMW8I~`t?<~I=MLPjxWs?;;_>wJgzaZ7J~ur4 zRjIQ!{GooXX%269Q?}E;;cwbYJ!9bSV@m!t@R6G&&n9?qV`vCr0$IoZ*UeBd(Arr~; zZGIcAm7l}IYn+n!WbpcdGTk)rYrVt^!L6QR@JV{TtRdX$X%3I0_qPPVt)5}ZH#W#cZ)ax&Q!YzJ2JZ`Y`Z8hBDZ^L7ak$N7%Ek0o?&-$C| z^Hyo#%eTvPi^13Fb=bP_iIXL7FSy0egxme_f$%d0B+p*>X1(wFApD;0j~>GFJ(oWC z=;r|2j>1-!{9)ne{}4|Cx9`751^*|6^rtL5yuRPK4*ZqA54knG=tY@sNB9&yE}9L$ za#5yx48B#Li+KmP`TY!UGgqb?KaKot{jvE?3isFh4E^Euyh&+zs!LL5TXr zf@iNL%ROOw&*ft4RSI~+O%hiUUTT(j1^E5*vL5z^PpPT(!{6r>p98n}?OyyW-0Hsq zZ?Dg3e1Tj2A$&diut@LQPY!Rb=LgEcf0UMfc7xk;900fFxYUc^@Z#Yzc-CplF$diG zkRLuo$Grw{>qB#R*bp+k74YfX#n-_zXx+Qvw*DW7AIPuA|8UzLBW3iQU-Jxb+aBw~ zLp_$?Zv(e_hQOz;k>xl6Zt?TrZS?&=2jEs`uowRcxB9bZ@|@q5`n*gLxYbh!zDS<~ zZ3(ydZt$bcWO_5;R{v%%egSUvht2F+fAtQsUB`l3Jz3x(^t}_c;kF$$gWGmA%8Lhi z@n>+`j^bwVtlzeyB=E}TWj*nS+jdk2Ua6SG4}jMlB>h9=DgopMk&4C4Kk;xA_f|&9nbje`YV<)QgXS+x%{W z+x+f@H;pg*uX}Kt->2}~`h07u?4I>M%`Eeq0iH|mw2i7Y zEoCwByzmws#jC=tKaJtmpTE5LOt|$Y5PoEUOm{!r`g0UM;hn@khg*N%!cXb>$@sZF z`(XXa54Zl5g-_7y7tP?-pDu9g&sZwDdQz^y-_^LX|l zr^eZHX_smP;qN#Sequ=_GYbgU-q z#Lb7_eI>pI{z%{VwI3c&&x@XdH+Uf9Z7|&8pTRBu13Y;}sV8JU&-t=?;=(O|3b^IZ z0k`WLo!El@IRJg@2gj@VtcqzTEx)W~ooQ7NeYjDf| z3~uos;1(YuzvuEQrtdqB0=K>;gj=0i;WphOaGUNQaEosWxA;!*dV0M67u@O@54ZfY z;FfF zd@DTi7m42w_to>sXW>;w>V5}4I)>zV4!8I(@QS+M313Kl&$gH1dYvvF-14M^TOTsR zyFZY;`QXp>doGH@OX&5UO7O~&B~K%GpVzWpwS!;WE8ZFIQ%U;Y6P~)B#P@^OJRm+8 zo3}rk$UF9t)5kIt7jYB>Nx_pdQQWu zMwb4^EF#ml{*&yX-S&n7kOK-^fRv8{9jO1wuw>&N2_CDqI z@c8c}Pj9$wzr*13VoE*Z;KTH~!!-D|?9!i2Ui<{S%b!xuGq~l6T2%hs`fr}ui&uf$ z=b&2fQm3TO9&kJF(GPy}oWxJ3>*s}e@cCV3`EG}&4wCr^f*02J|6GIHd6GNuNcy?& zD?Fl}9}el~*|)hxWH}~4)}kLN4%RSv#P@2{%|xBLU(wp@n7OX@hb z7;bs?z(4Bsl)Lae{xZLh;m__#{o(vQ`!nZ+{2T?IFN(xxf?J<+!1wF(@^#=(%gg%H z2%apgcz5`WFf!e~@au=A&M9!a-aQMRII{F%Jzd|Yv=v@qrQ|;eFQcDx&%;}kl{%lm zZ|ZjO3ZABu#78XV+5fM49?#c{7xUuwJ@z&}Sf0U%FRA1C0=TV*%i*E*KJz1Ri$4v| zsrPNXgxh%XFTC@1ng8g;J^NsNiw8ebOqOGIxQ!3_;8pbd9sYoKZ7I`h1iz}|Rd0As z9cPBZEq)$+NeH?AxDsyh2jR0T$og;|e&wt9HTa=QQvXYM^4a1ay?BTco_!9CBtJ)k z+jQf?)9H1D4DiBfWPWqPt)4<~i!TYc_{#85`f~%g)!7{W=DqZ-7u=>h5N^{Q3Agx3 zaEqS&1*Qh3!O(x1a{i$4Xwv{CZEgj@W- z@Zf&ZuQ;VV`)2Wp;Vt#^NFlhz7l+SiD|ws2Exs-MjK0@&B>ZD_$uj|-t(na4I=IDe zg?GIsc`m^%{w91*Qi=ZtxA;({<=<_;q!~7#aD*M((7U!;TGQ= z-c9dwo(#A6S@1sE&mC}!{|COHx%596Zt;)cn{P%ec^lsbCBEq(yJUj!K+=E5z0F?^}c{{gtgABQgvFZrLsE&dHWhUSl6_W$o^ zJop>Up9gOF3&ZPc{`zo>ZwBw%Qr3q-aEl)Sf3EA#GPuRBg^z6^`A@+u{v!OK*7F{2 z@n7M2G=IW!|9?MIz^`b$AKdbnhIi2G;4R@6-vORV<440SeiFR4_HzT=;pvu_q34eqb+=gk7Q_}uUdA7%ei9d7aU;FI-x z6Z*g{ejq&mBpI&);TFFX{z3bH2yXEw;Ul#E=WvUE2j8skr;e%Tvu(fp{Fd|~0etsv z8BdD9Eq_UPGR@x{Zt?BlZ8d%*+)uwxX9B!pUs(?p!bg{sI=90o>U&&+;AQpsf=BRf zRV2?#c$gK^A0Pc(Wqq^h#)Z$)>)=V?o9;;c+2ExXh?j)th%R0U-g%;UEqEh6pU?zu zdD_A)Pgl6*=?^cTLi#fjZs$dp!&fJfI=8~@bJ-qvX}u5s9Na!*$>BC#U${*-2i)Qd!Y#fe{C*uBui$omyB>Uv-p|$q zZu#4K@$T@n`u)*;;fr;HJ{dpH!t3gLWnaMCgb)3D z0`K7q=1HFDRXmq(@i@}Yc<^Q`rOq^P+g@_Rt^RWGxBC2ARrpbTzj`CM;{s>-qkJR%4 zo<+YmDr`0RJsX!SPcpcj=S&M9m0H#lKX}z$GTqYf9&IGP3B0QwPqcIQ-2>xKctZ!@KDfRx&t?-UNq%UW^_zN!{<`2()UU)1&M}nu=B7MjL@0L)! z4!rU>slNr>?z`&@->dh@^oFnbTk;Hq&(ZTd)8Jz>OZ}_iqeqBuhu^#>`47U!>-CG{ z@K+Ng&mDL{?b{=G*VD3IeTGl+mFb4n`LOlb>WKxndJ@7{>-wA>ZuR7Y@6`7^mxre> zE6cGOyh;q2-(K*``kY9A_)ES1H4kp*mzTg-=ySe@;Sa(~e@?>F-IO}t!9VJKeV^e! z`bhoBYRKQ#=gZ9`Pg-~y{ob_fa9eK+z;`W|I{o2K17vy);Ftf9_-63(y8aJ<$ImA5 z!{95=$$GT_K3%udW$-v#CH??B>oD&qsL4cH+@%diMWt zkjz(Nc&b_wpAKF?_pjN!cma3^T@OpaEq_(G<*)0-o5Mrs{b`-xmcK9D@(=OiW8oEF zOCM&!E&pP;r@c)xQJzaMVPE`NNFxKDs~6 z0sop+`dk5isF>9A2mDfPUC-fD^}1&_c#OjmKN5af--k8<-etMOFNNECsMf&mrjR;M z!tHxTF2Jwodz;_Ev(1$C;S0QnUVltb*R%hAjbysX;Vbn%z#{O2`n*zUFJ2Y?wWQS3 z0B+}HX5SBHzF$LaID-QhNl_4ne#;cxW0 zhRJXnXXe3eoLT0@H^3L?mOku(TmGYP%YV*`-+*7!zJ+P%xm;5E%JvuoZsS-AxQ%1k z;WmyHg4;M&8gAoQHMosq4d6D8wT0U_HVAIx*l>7ceSgR*xQ$~Q;QP8uf6l>^Z7bJvrg?^u34`;Wmy{hac19rH*hL$GXEm z)RF1VfZI402w$2*;&;Gp9Qy~p_nh?QI^4#wyYN7Lp5hbS#<8F9i6^E1ar8W{jY~F; zC5F!_EAS*k&)j7v5-%TEK0*>IAp(svq3Ot0{0BuV%ro&y@9WFWknfgYbphr9Thg+op^Egxh!(rm5$0 zDWm7FlEH1fN&_!gPwFfRFV{%+Yo*{X^gT9>;Wl2if=|`wi3Y-Lyc!NKqSrfC!EL2oc(jT=qjHZFC9ue&aJhQV#z7y~amNtV}o z_>WmKzuVv?2T1-?@Zn`8&qa8<0O{8&_}e_99Oa6E*Jo_A@gm`v%?CVlzUU&>W zpHLNU<3=s`UfpkYhTC&$z2Mo~N_`XI_T0)0_!>R`wh?a6#q5Abf1&+^r?@EddjsAt zf%NAqe9Q=m582YQpZ;qkJ_Y=$Uhk_4f2;Sw_JiB{IUH{5=VZ98pR3@uer|+UPbzg^ zhTHmi3;tb?-`>M*{rn0a)>ir)reOV=fY?8mHFBRxAk)`y!aBC|Eq9YKZD_`66yK|xAik*YtMdm94Ymr zfZO_+9-e5Lp#L6nZ~Z3c8M;>EV_1eaofcwtiNE zzo;V1u>;)J&pGh@{?h+l@E-a+-7)yMXOjO4Jo{Mb+XHy?_u|jsvkJ>}zrwfcb?}gS zf0OlXpB`_=rvEE>Qo`+iAzygAj8abtc-wd~Uk$u?UoSove)6lXZ*V(~Jphld_lMku z+jjjBzD2LQg=sJIVg0fA$nb)C-)2U*t)DsIdGvE{MYz3(p*p;Qe(q=sU!vc8)ft|? zko0F1+_v9|@ZP$9tb*Ux`{6gj&li>ar{Tk*ieG}?*8N?y4xariQdic8EO6T{3c+o= zCw10z-lmJJSNGuGOGy6jaN90I|LNJ!DR<=Oq;T6V(!giweV+bs+b+t$Z|HTVf$;pF zWV(TH+b-6?ZM)b7x9#F6+_sC;aN90!!)?2G2tW8j>ih(^?ILU^&wko=5e0rMNS0T6 zxNR5yUc8YP9|X7UVm{oqi)HY4V`O{Z54ZLF7<^`DS znU+fb-@zm3{T@Hzb{-}{7temq*XxdH;1*vL9<)JzzdYRH+rk5N{OUJo9O|oo9XoxApb~eD@DojxoA=_Sw!e$AgE}@A1hC zk9kvmzbf3$GuMJ&IVh&m1%9}JcrADfeGZ~C z+_v{#@O{l?xle@K_C5nXAf2qwyWzIIAAo=UCVjaDx9$A_Ji-8}=O^5@_pm)Z`#hwH z)RP!)+j}bbgj(|Z`Qf&``@wtYb3l#Yw!OE6H@GGB429eFJ{sOvzt>gCyg^C<8+aU_2NxaCg`w>+7>cwYEbJzlB@ zZ}42E+X`;e?E<&y_VwaJ;kER=rW4?ne>U9mFZSYV;fM9P#q;pLi%Z{c!)>}>;43f4 zb`-m}=khYo=Ecjv?fJ4w@ZQBFZ)bRE`Aa| zMz4$AgfELF(|rlIdLs4l?2maGcoKcyssg-;*53kNRG$~_29KXe#)lzr%M<9uw|Vhv z@RRzUw_y0help!JaC?r@r>|!pit77s6TxkLNC6*`Qu3F8uiPigt2KP+L|IP;d+|B& zFBv5NUbyAC0gtTTr}+XNW0>T52S1_vozQ=I_96NhsWTG%-9(wM1aNyUJ|*0qTh9Sc z9aHk>ho37YUK(!stH3RPWB7wG@*Ha`c!|d{pWWe>zdzjakA)}bBz>3+PaQ0MUI0&7 zOnd|Ug`P*)2JaY2>O2IuJeS~`^f{m#@KpL7$5XiF`2x53^6BTfK19;z@1nvjPg1ze zS88|&z3(>%-0~EI+kBOQ2j!9e*MwW1mT-H2L3?;B{oFSMzBHxG|48`otg>EBhud_Q z!B?)5^?40^U=GQ12wqOd>l5(5Gs*m3gWGhU!e{1|>Ar>!()X?XfLorZ{XLg^QvF_` zIPl&dB`!O>`*E3WKKKxQuTFJ%|IiX&58geRcu)AQzS4*O@Cn5wekQzw)*lEDdtSE3 zHE`?09{7n#GQS7loAf&IIk@Gy3!mgK%l$F@tB=gr2e{=4JHT_f*nCBXj~Fj;3E`F} z1AK^%W7*(S3rc^=z`yGI5-Y0-4dB7_0csXS`)`W+NEOm5*_tNLzyTjYwmFZ4^H~%X6r^5sFzR6AS zG6!V3JK^1Oh+l>$>?3`+1&{hh>WMwjv!5w@il>8z()Y>agxmLY7lTI%mb?|=f9mt{ zb>Nn#6@0DU=idSTN&7hizDSQV7s1Es{X*;DHr+jNo9+R4qu0`(FYvGdvK%80^6Y1u z?ecS6xJ@@Ve8^6T_lH}2WBApr65k$f@uT3a^*a7^xW#XW@7*N%55g_}KD^>)>CbDp z#U~jo`Rsm!8TveqFWlm5!XIsx-){=H_<`^gyCr@M+~QZkTk7{JZi8F=Wq7V2$$t-S z@gawJ&To%>@^e(U#b<`U+b{9?;TB&Terkkl@6F*BKNy}`pEn-|xA-;iaQZoD2i)SX z!Xu57dLF2pJg;dXv9C47!P*OMN8;)K+b1wJ)~)R7DRCYg8v zc&O0gHQ;?0$@gC&0bFwf<_I-DE_?uDPPBXQaO_KeRvQ2JaL{wb>DuLCcl?=$HE zKmShhOoC^=E_qhKyXKTSPSShGdUYSZ`?Tcw3cs{g@>Cn+IbS`RNIk9LQSVAzM|hXd zGTm&Yd!ozHv# zA8}mz`5rz!hj^&5p8bp*ARY^DeJ%jcyGP<{!*}R?tqtLc%gOY*!T;9JM}6QA^!bs= z@NL&y%xA z{)F&&2_!BTyyjmr-2(7P`o59s@WcANd|mineIL{ycN|1f->Zl@RF+wRMB@4-9AlyUD3eBw)q{|P@-Qap-&uC?Q+lY0L^BKX%S zQl~F`^l-_O7amui6E6w>cwh4T0iUM#y)=QJZXwJ4Pk32n)EFiJZmb6 zPYO?2OnyHzJgAt&7lPN>DDmats~1XqU3e{hFJBvYX8oMf3!X*a>+&~zN07|dRQLcr zpSc)bQRizD{F<-SzaQS|hWI&npC~fjJMdI>CH^&hMn&;W$nR{Ay+zDmcF$?z-sp00)P z{(60C1AJd2>BB$pkkzH0Gw__5CH^)%(=+jx@QAym58vT~;)q9{EWc;VCH_(QIT8F$ zZi&wTkE_=m^TTIulRRbM74`gZEqHd_?pngjY>+(N;feKqI78rZ^GN(8_%6M_WdVG& zZl~+vizCbaD+r$XlJwy;Jf+?ratl6C*UuO5qWU@g8~jU7sXx*b`P-JuXT9!_5dK~7 z8}Wt5*XIiJ!CPOHyrtn+ugZMYgtwb7@h#v>ugG@M4Ia9H^ldOaw|>9&M0l61vYyX} zpVj*c*1_ZI@$Fvtc|A{f3Laszh_fm{ym?ppLyW9 zE6RFO5l&fS|D`~gx}EjK#qrx7$o(~gD=(dU~Awd4oRK6 z;onL~JtyFsr%U{G_{&@p{}g`soWy^Iw|*=he!Ay!xs*YEjt4LLUgj$;yz*k1ZfC!uM8_JZaz?k4rtd;5l1J z{^IahIzCi`zti`nG=aa>^NF3{@AdQJ0C?dhQs-EBf4zTu4*cOiQvWLWVf`Gv6MkCn zA2-_+$8JJx=%te>hkA7IvoRaw$DT>Wl;5UrFLq!{Z;6KIDYo%`ILG z{-=Ji!Ji|+2ModO1vNZ zs-7pT3~#UJJsQFf>3OFP@T%7&e?Rz>wbF;N@YDekzXTq3qx9zhe3_mXItCx2*FA&b zK^p%MURC$|-{@7Po{)1q`+swZcvbj?6ygow_0q`vwu8S)AnR3c_(I)J4Tsk(A$?c~ z*J0IX4LnXZse3#8wQlbR;Gt(rou}bHM#y|!gSXfBQ9OYAf0pk12Vpz)R@3Q0?@Pc~%B{jT!URe)wz@G%m`rrp& ztmnNe!N2)P9rfX#u1J5{!ZYY~hhFeFX=Hwf!Mg@Yp2_f^^Tijy+oqFx*1-?y`R+aN z7k<)*6Yv@OeRkL2!J(wi$MAdE#XrDX>wU|i13i~lO1+*K6W&qBvE=X&h2-~h!;{?= zFAi@KOO|5=`1iz8XI;3hKXc%j@=E+N__rX*za5^xuGDi7-g3F*IS+5F=g;rJ1Hw!E zEBMDBlK(rrvfj@YSI^(rd8Dd|Wj#p-kFMiD8u-Sil0PFnyS`T{JG{zOsWUHpvmUP& zhTm)>@x|d`+ekml!so7#`YXdH=yqKL-YT}_sRuvPU*@X`{GT#XPb>KJabk>b7KxogRE1K>;bzQl3x4K*cxI(+aV$v+ofEwRKef`88=z7qab_ai&u-F8a+ z0rUG{E@Q|IQ&P?!5>!r?u z@SYbXzC8SHQJHQJ_;T&TPOwV)P zhKE=t@h{;?bpP@Len_tuL|rKLTAv^3_L3C7^MJ%2$w*4Zb|BtUpiS z2Qr9%g4fggdBQF7?Eggl-kiAb!Frw{6a3x>ncw_y-?fsr3_Q_%iLV7;ep$RFyqq5A zcZWwAEb*h@)ym0q=fETA{a|b1;q`jxb$C_X-k-v4d;bi#?LGWr&wkqW9uIz3?<-3S zzmiPW=iKn!y4{t4R~;hL`vV^EOqP37_yIk?-5Fl$n8XLbnd&j; zdvqMz1+QF6>OT%&sn^S{!FwE$dY-_mM3=sOg8%p?>q+<}p3CLYU*hrMne=^J>EV%! z$?xZb$5Sr@FWOS-tPLNh*OyzvM{Je)d%=t8d8gs;nXhH=c_GEO!Mlf& zI*-6tHkEp=z(?qHvB&VIA0_`Mcsf155q_y>|3`Py{=?sgk?E#~U(xfB`QY2yO8sTv z;d;pQYQyX6dCu1GFN36>Uho?kCI4{vX{~cQd`3pevkX4ByVSD{zV)p55qO;CGTkfi zlzN`?G2A{!e1Zq-`Ka*AJo}$s&-=xP&v-4@u=FQ2 zJn~KPT<}LNByS0Lv46y?!z1bS!4~jq|4ROz@U3;E&V_K>e{F!<{_7vO?Z3{zZU6NW zZu_b4aNAEsUg6o#%BAGzL~tADGr*tg=kfe-+fS8&+kUDRJeD3GwuHCTaj!dkWDQwQ zhQMvyn*@*cNakw+yi^of57)!v9hCSWc;TP2d{4vuqDr1y@L_ts{RMnS1j+vm-u{+& zLcn-JYgl}*=PAId+v;TIS zP#bQ?39aFFoY0FtShmyQa65jO4!7fnWpF!A*aq)7R_ZXn*PR zhK-(mp7T=joP?k6BymsRIdnabsq3TFX`aE0SMcIp;O}+48V`S*Lh4xq_tp2Loq&(p zCh-s9m$JzGK8MfH^(3sWr#4^z>UD?6@SQOve@1vmz3z}5o?DN@tH4i{ljTwq{w$;{ z$L{ce+A`g~@P`v5ekOc}<`0CY36ehSg@>#m`47S~21uRv;g51k{8RXlfs#MM7WsGU z=OexT5)HmTiPYZ(Ztt1QwAC}u;pFmpqyju?cZq8cU##oZD0pJMA894LgMMB+4iD-e zbv}T%())j&!RIuPzJ<~C(fTkarqme;{(YRpr-AR$?K&g8e+9`?627XJ)L9;WUC)2E zfREMdS?%D53(ImG3g4Jfd=$Kgo@dw%pE*zBkHU+rmHE8{KdtxW-iP1S?e{JGsK)zj z_gqi%Ka=T3gAdj9H4c1cU+G&`_*p%E$PLe{&lQ%3f7>B>YQwG0mhc-oU)|un?RW+r zPVe`g0JrI`fG6!EeLetRn@#$49v)8Le{~mLR6nP`fnWP7`F(bH_W#gn?LXY=PYPdo zK;pB&M}3t1x!`y7{VnC;PxNzoRrruPlBYGip5BMh5neZk%+FA`twGx*ZWD2kCyHEZoM= z%J5#JWxH+zxAF5&cq6@!YXsasmG%w3eu1o?SK*y>zxe>(Os`{x-|g9-L@nj#obXk8 zKFS~dz*nYQ1s?0Ccq4cuy>8eMUPzCl`oX97mcEUK`|J6=S@8D>W&gec-ZGQS*EV>< z2jYj}(e(4kC3uw^68`|+eTOWU_i#H73AIOl&(_0tdLMF3_=6Bqe+qcm_0rF5@S)XY zx<%m=Q_J)!!9zTh_=fPvdLK@6_|H62PhWV99+H0`{I-7Hp9^2C{ageOq3@Ac1-JF> zfET~x#bfUE?6c*`1)oq%=Bpaq#)sPQW_oV0lo;Cqfp{8@O|YT}pSAwtV`^a5`8 zhrfdl*5^mk>2)(32P{4_{G?t7DFbh=@5iVF?^i^Y*WdJPvYwBD7u5G9E`!_g!y0(M zDU$yryr-o1IS>D*ru6MC{HWfC{|Vk}x-9p2`{ehmKR;JUpOe6+>hWhO__agw`xW3Z z^!U6JytXbEdk>jScapvrcM;+T>3#ky;K}v;=Xv-WU2m_#-|Kq=LhbjQ-#h8051HVf z6G$I&z!&6@_{MOHZwdeYL*j?Rzv}uw3Z75*<4fQczY3m4&s&~_Z@4b&&t-V=+cN(j z;SX;~{C9X|J&uj1$G^6`EItXm-#W=t2;QZ-^s^XzoqlgiOZX|hUe+F-AiC5)8lFd| zI}z@8MdH`Pqo$GNvK78g_nUX%=k$J+^8YMCsT zW$;VaB+nXnc76ZGQFyt85`P;0KCP^858xGZOFhrvoAvl7#9_(zzkcd{dg0)uuSxw$ z;CGwL@27$vyeZQy0#7?j;!D6Y>U*B|!{3CHJZIp`$4fmo;qml1;TimKS()xFm^=b#eshOon5X2Y|@mi+7Cwq4wXpLrsA!W@(7Tc4Mnm7kNrTTPI@rGZD*{YX*xLj7K+ zlJGvdJvM@$nI!9H3;3?uQs)5pa6L{Q3ZJ6qOXtDc6_h-S;f;0N+Y7h&gYdTcIpQ{a zoStWX06(bri$*x^+2<`KWPYQ;_2ZgPVR-H}Qh#yy(j>Cn8^X`&d8Fp>Oar8j5%70G zQqMSejBgUZ9e%u+tPgwPO?;)!3vi3S20yS+^1Omq(e3(Q_%dIqC&UT)+t%B&;U!Nv z_>*-K7ZpBplhhd-UVEwJ$pw$&BY6tIr|R)X?USDMTq!4c=D{nL5MKqi>y_K#)%5WPI=Dn>hO{$0=z*xncvv( zV+qBRz+dQgkqUlwndJ9{pJ^<4vcYYCR|($XvgBz1zi?0Tw1(SzTzkSx>V9n)ytID5 z-W2%t$;O8RCbf3Zh)cXX!!fRfX_(-Qc zmv1H==M%vT>wYaGJbP>T{etk8`kY#MxNm5wzaG5$URf^f-~oC*u`j%WKKD8b{&v3P znFZgV_Z6&!pVa3acEaQ8`+1JTAM1V5*WuOmxr1l$2Kv5{ukexo%5sl%#I6Cw<|i7RdAl!Z+!2d9&a(^>gcd`1cu- zXD7U4KJkCxV|Bf~4sW$k;_txQb(Z?S!i$8J_z>siZ|i@D))Jox{_u?~#}x4O|A-fa z`^A*J{_s9}9k3oeqV7+dz&q-4=?lNA$7uuMPuI$HXTjU(d->+W8|wYlTj8hT$$agG zU((Mf=iz_%mcCtuZ`aTD@8CiCB>pqJQ8}qU)&5BI{eHIn`ugjXId(|rQB z_rSb@*VFR=5p+Lh>v^HSWxk@pzweXj`oaqj)IP&k=;xZU@Bv$;&dTuT(Irn?_%MH& zZYOx5q~astetI5nJp7Gb&s_dlhpFZd(PKLQ@0#}CutJM{ZC?7Egs_p?6Vy#?|4f5`GW2oKcj zrx)Ni^!-Km;2-q8I&a}M(#dug>azT8_2iEueMk$pJ{0ld^}KjLxLpq#48NRHJ|`}K zx6tG8W$*-#q|VFmGi79cZo-G?ecC>He%j{ubTo+%3y+&z@~415()0G|;H_>-o_g?e zX=J{#U-j&B!e_F43&VftdF+aCi*Es+JVxpq47d2jaO?j{_*nhidJNuIj~max&*}B< zXYjmPWP5o7@1x5jwVo%o{)bH|@fqMTf~8+W;C>mUZ&ToV(@USXz)R}*zYqSTl}z_E zd~rSL=Ph_;-S5AITmG=uJ(usZq*7;Ocy&qdla{XUlgR{s5k-EXG`vqfnO;SBPJMqu zd${$v3p}l)@fia@R7d_{68uyKsb>W|f!=qq1^!P_9mn8F)=B;g@FIE~bq_u*iNwE! zC)WE^L+W)QTd%C1WM14KZrep^_@2hHp0tG5k1F#u1n#ff?@0KG6_RHWe4pl70T0($ z`uqldU%%fi+AZma&98mGPg1yjzfUi?#s3Yr_&acme+{?zvU)z->RFaj=C>*Q^gHp+ z@CgZJegohGbQ~B5UtVA0=fbn-IKLXcESW5?UGRlEejbOvE+zS|!)?CadGQ$cJ(o*+ zeeXmrxaFw{xAm|-e9U91=P$VJ?*_s5N0#|r0=NCwD)^E^5`PsQQs1L{8$KnY%;z_F z;Wkod$OoQ%s5DxZ`viDPz0V=#BhUCe`dol7yiIw@pIzPgNnbtidjk34iDj}r{;oWF zEBWt#so-+|UoEiv_v*v#{=N3d@2v06pKfqHZ1Gu$JaZaK{oCNlwJ*C|dBRHS-~T@V zxA{8Z%HzyeWBr|nE_dc@wjOUhhnLpx?|$#fAI>%1Z}6DJxudy;fjx-wK#uufTz}f>yA7DvRHf; zyW(xxI=`|So=Ed-MxJ2J6XbHI54H5X-)VS#^%t)EkuQ({ z|Kz{r;+}3ixJ@^=x>I&!&F%bE7@k@Gt)wfDGu=R)ZWWh1(|uD=8qpa3L4Bwze-zhr z$H24czfE!Fai;6z{P*k6W>>teBaZKe>*Z*lgUHiZ^E`FMM{^SBpSSSX>R*sYhby0C zPo*Kw+}kvrUr7f~uX(bnJL}r-^;r&MeTul;>8Fhw72pXINuS%g^2gBJ&R<>NdU)>B z$CbyKZh%gAhAZB-btlh!xaC=nJi(ghh$}vplR*ERf!n%%1$q2*P`~Gjx86Icp2028 zJLCz}JU?9VajckMe}{ec-|}+Y@I4*aROI-TvwhHa9gK+k*Bfd$>oaIOa8yJ z6@n+wX_P>oAk9y!?#kn=&%s(xB)!hyEJt@eY2fkd%X;9e?o8MAu}=Q% z@Z=8u`jg+4$C<95?!0kf*^(Ut*Px9X) z|0@VjtN&KqmB*Ri#+tu_%iZ(a3vTl}2A=eX%;yAkXSt_v)iVQb>*9P@9;colt>?JQ z-Su38TRqR*?=ur$1eFyB*}pliHPkB;3}AiLN|O{$S0& z))lX}!2Zs*6<$cEu@`y#bO&(C0k{6=fsgLCh&+krM?#GPCc1j^>lzY)_?2n%Hz}%to2NExl_+f9r&iY^4PJGlWH#9 z`n<%I$I0&(RVIAO_``8z|+=;h&2vT?EOCO2(o#zN#cRN03TzQ=N3etK$yWG7TqrUsE&yJ7E zBR|Jfccz>3_Y~!S3E}n`CZ#KnGu`C+p|hOJ-P5fBf2QxTX$Rk}_f!3;?$ndZRZmZN zS^c*Gt~^dX0b0*Gm%HoP3Agq6INW#huVlaeoK|=0$^Bd8f0yBT_1|v0@;LPbYdzmw z@%o6x@81ahUY3KC-*MYFL{@i}x0A$LF{!kCVT#=D+50 zcm7XaJk-CQ+l8$U@!`JDoh9_^Gn%^dQ-R+i|4R+G9%XXnaq0}xI?KA;sdGaO$y3pl zr=Tl;4Y-YO4P1Gg{K@s?M;}+b9eX+V$1x@QFrFIxU0^^a65ip?aK3eJJpkU$6W5z>8sbf zPr33~4rel#;5H82a^-RI2WbANpQK)=&+a~?hcEi+tSrBdnbn>7D*0RFf4Shck16EJ z<4iYLr`yyOU&@uIE!;jEbU_|J-GJx2;!C^oEQe>%e_M|{ftn}S6|bxK@85U~w|>4x z9v?l~nd0+*>$4q$IEj4WHa=um|KED9d78T7ZJTiNw1tOt@YkO%$P=V_`nlpOO6c$Z z4~1KvG02l#Prfd6xqCfX1GnvBKRnu6nfPIKXZ@+J^_K%lcd48|ATF-lzJM~;o zD1HCr%2U~u-{;GJ%f)e9j^Wj<|G}C+hs)jbTMQnnx8yD5%3sAb-AZsfhg;K?$C)ob zT_J|K+&$e{@UHu0BJ*7NtGcGU6mFk&*ShjJ(+$+=UUj*9y7%F>eBZ;Lk8_r&kIyG{ z=cj7FMgRBpzy3RJV^(-|>%Wg)$V}sMr=Hh3bH1)Tf4K5zhuiYa@5(t0+y+^Og2AxXBym8XU){~ox_?;%$n zCx3EX;qJNOYr670gIk_=$P=J>5`Oz{IXZbFYp#^=RO&@tUduJz(s0{mDy!T25UkT} z=yLb+>g>u>+m*jJ+}5{&t~^eE{Pg0+c$d5LukqsB;kKTff>A%w-cb)OzR!=7Qe7zqpo4Qj^T~|H%;Cg$tkDn`#Q;(1SLu;42 z>*)%&dWOUIFL09m`kbil)Kl-b$p0q8Z9AIn%H!12SnJvDa;KgY`txpAp8Br*2jRB< zpLFGM@&{@D*RJ>mt~{UM|2x;O*K=%rPOcZPqPg7Nw_X%`RcCldR=7w z=&A1fcEjHpTfLc`~UsmE%o1qy7D;7#V@)1!&#TR*Pk13+wR`L*LHC#_;o*zy7N<$ z-y;9}4!7g*Fh0ME`1Qxu=fLE@fBbb#P~6GWROt8rGr;w9*ROM!o_Xvdr@zbH^Hs-{ zr=gL{GJio^W&A-Cs?)*XU%h{by z`S=`hG1(WQhOzZ|jcpFA?F^|Cs8w90N2@3YYu;N@?3m zepjAWt~&kU)}OMjJWid#n!mQo{ayLnx$?Aj}O;kN#)cI9#M2WtLZF86okKdtWMZ|ll`8E)g)ZC4&AzmFa#ymYz0D}PvhACi;5 zohyG-xYZw5-Ii}-&7a2Q?)>>&d331yJrzH=)nCSy$EiO^^Vf2@JAZdC9ssxTYCJrp zK1V!R-RVOIS084>ck90`a^-RAOs+fTe_Za=`Bu-X9CYRB=*oW*ZpR51U3r}R0h<52 z%iVp5qSrT^<>L5XdLMNRb!Wc*bWJw_T!#&x6s|nZbc1!eWnJ!`ZgqHEJqT?IFB2*B z@2Pi$7cU#~w~vOm(&w_rt2^~~a@9W_o>S8J1iJD#_4{c<_q*J={?%A>*>xc&e`idNEf57hh-^?fAPe;eO&s5|+)xbhc(+xAt=mB-2NlTLoAs>|K|Zwa^O zGCH~PYioWd>IILaH3hixIMZ#c(;e<|XS((r$5=0Uro#2HOP{%}JWl=~&A;8{PX44} zq}tnX>*srT^<6RppVXZ`I~i=cK4E?({q@IuzcwShx{YJW^(K+*|3}xk2Us=z?|(}a zMHfk^Ocx|crIebOE|ObH=}yyyq9~e@6ceS9q$q`<(M6-Aq(~+vLQ#Z45hkKUL`4*S z`+e5?`Sf^x-@X6nbY5qj*Lv1_?Y+)EmpO+x*EwA{a$YI?82>wgPR`NqTJN`q@K?iO z5%ndH)hFBYJW8DNJS`mS+e^ZGkF*3)w92_%8=fNJpEra*>bJd19?MhgdG-re>e?ogPwYL%%cs;KaUfmx@t`Se3dj=5a zaSa##dZ#dv(Y6{=uye@gnpIJAhjjkrn^}JU2MIVOt!-a2q zCye)Y=g5P8?-oAV*Wroeu{?#IXGuc)mxUMky7anu()@|a`^0%%Ukb;#%KP6tV*kgy zpDTRwlCWQ$=iJ6SB9tceZwui#X4;U)#+&UqZ>08S#<*@3zS;NxJH%7$o*d#l-kHM3 z`tOr2PVlb~UfEwbUQHg$pW%E1aqjmE;r)8WcZ#m$jPksB>snPk6aw!hYM*IriJzy`C2ff8BX+;h4t(!WVh_Tbv{3?f<6A5IrI7 zQRlhB`(}jpi^ya3&-41MBF^<+FMPFspTHL3mCg-y_`x~q(8B${3h(TB4vGigw{z^V z|DBgB>_wV*J4HC=tFG`mPlx+A7yfCLaNJ!c{Mx~R_Y~e_Q{XoVU-@>(bEohn{=IpV zg;({*ktcF0f82k^ z^N2F>m3YJcw$Fc`w4(4c#)fvaonzidHwl623BSo-c)d*c3~zt6@YB3~u5;w+kUGPQ z|9(yQ%FK{wweYgOf4(pNug(uSKNViX-+2C&JXW`kUbjDpTiu@U?|-Z7f1iq+SpS;{ z$K(EG!n4uzL-nEJP?aGWn)M;<$_@gdOrh+9tNnI;^0o)P}uy&=y+=a%Po z%Ck&3UVBg<+K(d7*TTp9Z9BwM=$>DR+qjl@2{{i6Uv++%urkM4Q4a6V z?J`qWqh`WUpEkl#pYFmZof!J>>eyMOHerk4o^|D;)KiCA|MLL6l4WyDhkH^Ms>5&ymN*mDwQN;Zx!~u06v0-yhoV zBY(E{X%~lt_w(CImJfACJqx|xCd9el%aq>}L>-*l=*PL+F1iXw{jVdBjW?}fxYK>a zx!-BRQU9lfZ>bQ*GvB%8@rbDo77NGmyMjEHC)@LUMD6bl5mWzuF1&)@_KkRo-SaDP z9@jCR*K*=9#8ef8`)O%(vUAK=Mx)Si9pdcoOr8m$Y3koz!d(;fCy&)3&u^F^?aR9B zN#VZxL<`7cd8Yb#c#&{Ce*G+b>jR;K-^hO-<^M}~n%`EUV%%B0p+5NVeiPzcpR0t= z+G{frMV+17wTUSb{^=zguf_K#PwMzRFSNg(+UJmGns9%)B6>_bh3?5G&iP*wPigPt zHQ_a#uM-dEO9lw6V5hon3Kj*w4fnOuMYvoY?9?tFBB=6HM z`U>}ttwlGICw2UKp2vxEp83MDo~#gF)?e3p#kuA2T{D$xjc`8=kJgjN@)UcX@2UOd zlp*}{v+(wQ+wbDZ@aG*R{riV(KeusB_3vFgUO0}gdI`L#@Uk1i{9P)1_4pF0L{~bu zIy~qZ?cy5Yn3rqGV|B>${8NbYygVix^YXm#CV3&xGUt|O3guZP9OwCOkjL_*{=%wa$DSDKg!-T1?<*be-10m`c`6IX<4$$*Se{IOe%FpT=jkLId2SG1%U_?o z$+_j3N_lP*j{1xykL4-!JTs~NH1fTjU6QehUH-92@ zuu(XkH+?A_&zp8Tw>nsUoQLce-p%v>E1m-Xo%FQIVcyO2u(!2~I>O8QZ4I2`@hIEt za0#`4ggjRXf6Z^}CZ1yV+(4Z7lZVMOo&1jrN6tCqv3bw%*D+q9_A|({MmTb=7f+sh zHWTNZCH?z!t)7pPzpQZNtmGW^j4lXwI-A4_K%V0bKzKLz7bDa^KhpF#Cg2ss~q0XA18km z;qa$9$Gl{_|9s-?zmzMRZ{)H3d7l3ean65~Kaa=b z7xEu39QmsVNB%m(k-wR9 z{;42*wBL5Ja~zL_?x{nZ$JLQMPm{m9@boaOD3d&vGp%K~(@^5qy^lwQpY8rU z@yz)wjDLx=@93VFh2!%TYs7=+J6oy!92)O-;r=#V^b>h(yxBh9gT#5fC!BhCzUGqu zRN<&YE$5i8V)r*9&i;$ZGmrdN3P=8H$Yc34E(~`XK%D(!$upn)6NLM26+K8E^XIvL zCUNsWoE0WGPxxm;;~V2`p>V7-tAw}9Of`?TIJe{LnSfINZWE5@Q$LW$a^izi2Z(bW zPWIm|H~#|i*AR}^f6j7_dCa^h+^HFH_ID&tKKZ)~$2?||$MP4te<*SGFHPXD3dcIO zNqFwfHuCuWdFOWR*%S%?Y!z&x!N6c9UnZJM3b=aO`h?lc!~zGtd2{{CpPk z`0EFu4yOq3T{q14S;8Cn>pWeB2Iyr$olLmuUf58%kv85c~W>kzimEwEKgdya6=KbUqzm+!Y}jNwu>j*J$s3_ zqH!HjGrkgUSpWC#vBdHBO*yw~uck=&=RDzfd}%=*%U|sMUPhez?MI#h^4}!9x!-mh zdCZ@2Nw{GgarRFq&ua4L3iqei(LC~)KhOOy5@-M0Tg;N13yLhsWqZV_J3 zZyQM-8*icK$))yd$TLqk*2(9@lXhvi)2qaJTXGV z$HF??!nx&ni}JJ)j`R7;$zyr)JkKC%|2BDs3CH>TDDgy>hdWIq&UJpAJnxWyj&Q8E z3&~?SGu^+OxcPBD|Bi5+&wnZ$=krIO@qgF9f^gLT4B_8>6zX5sxz&FijjNGx><`V! zW8*6HarGn4b-P(O^4ueQn*aXDeaJ@fybuQP=sPrC5AnU)|v{+!#j_fjPM(_T1^myYDI zJjI^pW@^8IJR^kTco{36j4Q*PCKKm6&nC}C@-GmM<7EkXEN7nkUm?!N%Ld^%UcL~H zzn1lmkHIA_T{{NW8r>SM7_vk`D?Zgceq|S*3V(W z@x999gxC5rR9{d2C#n9m1XF66c(2$+L<48-!yXi^yaCLic|~ z-25&5cj9&kPsM zD&d&lk>ugJWedmrJ|GVYg=2mnB@fpvPdMgxk#NlK8sR^j8TRwHoLe0}p>b^#j`{tBJXZfaAJ@0U zIcLeU<3{mj{!df?3;&cAj`^+R9CeF2h4$5n^ZcGE9P`^s{FvWMg=2oN7Z2(=OgJ7N zCkS8pO~`pa`9GuaP7{vD>&M7r_006~t|4yYMV<}9k!PFmG3%}3QS_a2yS6z+!auu( zPw?CJlgIKDdY+2);w$lHo-L{Wg?~;Fj>qeo&M}W^SBLfuiSxMHlIL^sUm+a(Nf+{1 z&TRKzN8J24zr9sB9%-HeTd8uKwY9H2$@}&r-p;&CA!+@5#c^Zw>NTznT63b}4c0w~KJp zVSw=KDq4al8syxr6&vtvnD8v;qsU`<3O&yZYQGJV`0`2NSbye=C+(VWr{%es1lt{+#aI>h`TQ@a-Jo=QwXd z9?Mhgc?J?Ue_lcSPrPN5XS+M>B1d?c&^($-9`k4T3zxHrb3LCIj@Q99iNAsOy;=CX z&c7GWivz=cbwJvG;O(OZA+WWwah34=$2v!y4}KjyrwBj2PvCWh|1ctmnhW3M-{W?T zbG!F<$P!;(D;)dh_2jX7=6OA{h;uzBljnQ#PZ!?YZ_6c*`6EApTST1wuaRd5`QH|f z*Tdf@kNGp*|0Qwu?;+1l@*fc15Vti9^~U;N=>B7gn}3@BKKlv6aon9D9LL@H!g1WS z6JFJSS7m^6o8KRhF}@rk9P2|Cd8|HZ-NT*kCC>GElsvo0|CI2Ve%mwTF@LuEmlHQX z>hPLyJdSJ?j{58tj{5xL-0EOC@w)NRjpEMY4SZ_qTKv4qIgUHj^9*YLqqnt-`obIg zZReB6##`*;y_h)Hb0m3wBL7{&{cWh|KJu79qer;YT;k?OeO?rf`n)L|a&~j zY!i1#<;-^ftHjNZ&sVP%j?X7=6pqg)e6E~G3&(l#t-@E_7CIi`-16-6EOs$g zIL_NAkjHXn^bU8LL+$sIXQ6PctINcb=bkmhdAz@o=Xdh|CH!>1t;G4E&ZuW}ZMdN< zar5JNtSlVInZ;30`mXiZo9Zg zxQ*MkN#wEl%Je!cp!Nqs)6~C9gje+2UKUTGdp@J~f0E~G;qdGbPug|iPNkZL`La>| zMV@lPbNsfGoMV2o-E#(U-ha9z@IJy(|19Ba{Pzz=Ik%h#DQC8D)IWzjspHyn&ZqW= z$g@~D>b62W8GXW?KB4x1ljlp}@O&qpJog;c>~Q`6AneR z^Dp_Y5`Kl>){Q)={nq_A5NH1s@}w45_dF^b^YRpV%wOpK#l+eF7I}^chhnOSjlyvr z^$B^*pVl`7+D@GPB`$~?#hc}0ew^?w{&#|Pg!k+mURST@+#;5soQ;L!@jab9mNVOP z_M`SklIJGjTS{8$_`5yDQ|z8`#Ccp(h2wepGV%MLM@OrK`_CRl>%=qIA7DP0_7{fo zM&AgZ;`x6PPvr-~9ZvAq)pTB(3*SE?w7<}~m8>Myt(|bxzXN%!{u%vJ<&3hZ{ZZr@ zBOJ%|c=6=9=Mmyu|7XZ^H2I$wetw7(y+j_%8TAi0d`j(0k>@MnP2Kaocrx9ypE&2N z+`>Bh|Bs6^gzxpomAcL?N@>c|NI2@>oIEzJLeJBU+WS}9rE>HUj`Nv;;z=8jY95Uw z&f|J4fzK0;$D>z-_i7M!+||x)sK?TH-x7}Vw~gdU9q*oV7q$1VC`t|BH{m#+|4Tf@ z?m06(%$G$eOL@)}UN@8{YULQ z&y&aUEn8w+T(BIEb1KLI9?Wtr_epG5a;^rB2NX% z`I~T@|NliE`)}I7P`Hx*K!Cd8{Qr32IRCFE9OwV_oLdyjgY*B!!fS`AC%lcHgwAtr<2r%r{G4#?56j78buRXtA5!~D z^IQEBz&QZ@i_qQN!e(Vny3&;M@ML70{ z{?3sH`@>-2*dHc}2hRs*3jeD?7~B)&@wePk~4x-DP+qEjx@72Olho0oI zIuv@p_YmiP9~6$yvCI`-zIs?c7dW>lCsUp!!oAz*W%8ufrJKUMd`az3A z-Qvl1PZb+Xyjh)jT(yK_ej5wl;g6fmoLdzC%5u|28NxBY?a7l`2RzRm#O=S>&&LZ# zogWu|`U#=VPdT?dRjEGD2)`(mGX5Jq@>rgX!QqA?YF~{!TZLmTw~HswJyGjWXH%F5 z>tSi(I0voh9P_fWZy48k!tcE(oY%DxKDJ(H-$gink7=TC)cIlInD@EDEBX1r0_Qfa z>QtX4!ZGhJlgH{D4GDGLN!&_^JbQ&>-j8V$>WTVX=bs}w&bdW7jq;o*yk+P%szx5m zlj(WdQ2R9UTrM2vzMaKW=$@g{9`k;?@V`9IIPzE>Fz<7OW8Rku$GpEO9P|FYaMbx% z;dtCXy6u1KT-ARN;#lWani^D}io!A8Q^;d=PP;h_xGA--NuG;@<8l8I@npNFD{WF+YCfXEn7ylXAW#9LxDe z@njAS9ehUIa@K4e_%`AA+}9rQALls_2=}MU(Gl$|^x=7b@vgAWA155g`#H{SNOfpj zO@w1yEy-i`DfDq&LY&9dNjS!pDSnJ=kZ_FaR`Fn5V})Z}v&eH6jVn($#+6SV8&}$} zR2idX#Cco=!ZEJ*#E)@(EF9z7Djtk$r*Mqx_)Gpfzc}8j3xD>`Fz+>;TM6n?9qJ0l z<6R^2SRJyx4n2um9nkOf!g0Kh7XEtKkmoMv7R67&Q-!`yI35?KkjL^Ad!9wq-haw5 z<#|y!*6mltlW}XRdGr=>8yD8?4}@dg{z^F3?cL68T$Tsx_I}~DLbp-L_Hk$NX6?_h ze|#$|{6goIoZEVCb;$GlwTSb)WC-v5N~r&J^;{$zpHC=sZqfZG2U1Db3CHVQo5*ANGj9t6`)giM$o}zdgYag~i^yX+vpwgx z#JQeF`RfO!K9Bsz32)^76P@EYDt7;A#LbV-+td+`^`W8gv+oR@w-Ao~{Bq&g&wB~S zem+?E*XiMWCfm97)|kedBOL4ARPtCoGqOS<))VJ??h(GWeQ3Xr{7tCeL&EVoNy*FO z&f*Pq&hvijIyc4nXRq6{)`OcYDV1rSNQMQUn3mzb-i%R*GS=*ugT6W zVspwlT{w=HT=JyWAJ6#=am$JQYN>GKd|fzlzV94)aGvm~@LHif(RajKQ2yP*|2MzR zvHui%{(p)8XMV4Y2NQ4B{y+2U+`3Gse$No@A772?lP9&#+-}w=YDWA&^D7*6yIwfz zHbOY&can39*phNSEF9~}_6$g@Z|*2x#eQ|O*Ii1WC1lcyE=_X|%CF{8i9V>#3A2sf0v zD%2Ur3-*T!!m&T33CI4>*ttb%O?lFVH}*Vj$zyr4Jx^!iJlmK;nn&fF zWB<={Pj%v4w~NW+U!{>UT`9b-`>!F7jTb+@G=Mn!Cz9t9%KwmX%==98m_PH*(D5_G z*}p!47YWC_{~)}{X~DnSxkYSGIrj_4y#Gxe%US3-Pw8}cUM?k1P2rgLy3R3QX=6g3 zZq)uV^7Ijoc^@dAZ1;>L&UJf|JeQMyzHrR@V)CT+bN3ezXaCpaxq|#VgjWp1jea4I z`7_3b8~!2A{t8zguJe`TKUw(0?yun-by8R%Y%)6|06dfSW<0{knaNRmm&J%>gf2woTtk~sVCC(qU7pC_J--Rx z>->;-UYQndIJ3*)I(Md==L+|)6^xoXN1cm3XFKAY^9J!?UAjg1m~h$>%@WUdXN4Qq zQu{8HbAxcqR}pzq$7yyL@3+J`=kMh4ubfNW;UD33f+jlpnou{?AMy`J0g^b=-{$9e1bp-N=(E961MxC(}K*6X%?h$kUzt4-1F?aq?KsLiayQoc(La z(}Vo$g`*B1lE?gM_k=nW6KDTk^5D1r>>dY&!+&Jg|ITB!`zsP>|LM*xdN0a_&&$RNFZLIR$2qr%eJSVt!f{?SjXbISe1eTK{;db%mJ@m26OKHe3di~6kHQaD z39noJ;@l$kqnv*TxBA)kFL^9yw&$$c{qVf>Cr@qRHG?Lq=N$7=?4B0Hd0qySX8`$! z3$N||JIRweF769AOd`(yC&_a?`R5Dwx5uN!up`KPB z^I#sU3BT)|5VnSMyLJQRKT9~~u_1XZKYpCB1GOJWp02_%kJpJOb7H9T&BVD5v&b`u z{CUFDgC@!+kL4_M|1#p{$MgLH;ds9Po^U+h-z6ON-!B~XKene8>+tJxKlbgThh&8RW5?#qOU? zoa_IraMXXLaMb^6;i&&U;jexh!X9vL*M?C3s8^U5aMZc9bGvT&Gwu&{Za|#tbFuIP zYfGf=a4Gryrz}#ulkhWwKI%ap>o?E)9Y>t|oh%&tTdwf24~Gu&oZEPBp*rLX$NBbB z@>m}H7-lhX&a+?mm;QN`KgmCo`aPoe;rbg#{f}{u`e#lG`5O}Fe%lFu;rdYj%g8^B z`n_5>>fe(*Hr_(-_a5Th?}Nfo|0jjF`#y~GY3CN@R?73NaMb?=@>rg<2SOdT5a&Fl zuMPcJ-HgvaKU^>C+`7Dt`mH1!pC7JDo|ds9+xxwo+7BmBXW>mk%&3=mirsS~amzXR z;&6xI!f{+bLH;c2cdqc}-tQvvw2b{3lfw=Wx|7HJS4<7{>_@y+%yB+EL^#gJ?i7ym zu^G-SN;c(rQh2}6Z8V=emghOovxIo7nAdC_?(m9md_MDY;ds2*Cw%9(!E?a5MI1*t zqkeH`@dl2+M=tFg^HSDd|4b*|D!wcF?Iry6$AY&H`R}2A2MWi!J(N6FpCR7wT;kmC z^TM&8zakv#_Lsu%m>u^2ZO$#?y_E9@;aInSC6DFY;5kp~AI5Ep@#Hy8IM(emoukh6 z{Cu?&wVyzq9>TF-^%c)3_Y5X(b;Eu&LOAxT`^kSF^*c>C`hAQ%R)@{r?_A>C?_%NT zcY|>3S6hYe_cz~)om<3-lyj$Wtj~MMV>z2W65lc2stgG8W%cL%s+Mr6-9 zjdF7 zQ?25^-E)rPZl#Z_E^*!;T9Rin`7ajU+Wl9O$LdyPM!2CjarRFn&x7QDNI2$wCV9+1 z%Kgs}Xa73#Oda`+ZS3`dvr_2kUTct zl|J5EiQ9OwpFd2V>EwT0IQ({G;6e1##X_ zz7vjq|04gR)NhGFu{7Qc8OMHdtaGfZo4wyk#CbnyC>;AqE8$olItj;q($_iiU_ZH0 zIQEm_;=z7$KeeAp*QnPu{t;N6T7*@ZM;|~pA(M#=Oy8&!&|~pha%yq!(QPy zk2>zlA0wXbkB6L7iCg{8@kMViJeG5o=Nw6#=Y5WFQI?hvc!G2R!G`)P4?meix2;|3^ICpS0PCzr)I3m(_V` z=G@eC$)6#7Rmu{7MwC33bEW&c5$FACgm@~rXRPoSolg`Gen)Z+wVy{h@w$Z}<9MH9 z8F?&cm8U`nYlw5suM>FXo8vpj8|pUhvfw$zx%E4r^3)VwKQxc(lE?Cl@;p7L{WIk0 zD;%GXx=}ov-7|_fkLv;QEFk|Q!ZE*3kjHX1n;izQkU0C-i3jt$NjT>BbMat)_fz|P z%K5i&_>a2f@Vr>gS)Q{Jan4!Kxv8Hee`DbleZJDkWBvo~A4r`2w+k=lpYywu{0phy zdxc{icz`_CZ}+?qD4*IdBF|Fcojw0b@vL;uJH$EvZ{+c}98#vggk$|LG4#Lnukv*0 zIGs5AFA2mQtP;!cn(2 z+_ONp44$MH{9?tajx6DSx)|vx5jslH$%qpK5tp)cAT5P$~w58&WXe==hBTOQu!B%r*eu$(GubQ@>sNy z_)C=M6XAFq|I#_?w%POiE$#95l}Ftchl@8;o4;1-TKpY2&dtN~c&>09Ul$2~{hZ)! zL;ja3|K-95dcU2?WA$t{Kin{kxaC>WBGfaBJg<;{jBvcqJDxn|pXL6isr@SQJS!Y^ zenC73-19wguG_D|QMW_Faeh`|c&H!hfA6?ZhZCJ!#8)Y2HR1j?V01cpY`oo{37*!( zEoV>PPuh{EfczbVqn=&KWB!%yA5QI8ljlz1SWoU1Pn88B=flLgp7Y7`8u=Fs&kCAo z1$ivzDEGfdoc%k*lkT2hgb#B5r+E7L$xFGcxU+b(h_6%5lZ4~(?lkBBJAOT958|A2 zfN<Uutrj}o9wd*|tyzBH3#t7Y@+=dM$GcVHndP4MiQBkv zp70HM-XQ-j;W!?DBah`g;Qopu4%gp2Socm5UMmbMy1+S(J3NlG6^=T05x!zksB?Gn zze)Ksg=5_tL>|lE-OuYL5V!ig;UD_ApFD4of0}R{r;m}x{43r6619JuJg*5yo!=Hu zm4%^j2Z{6kdGyG*vv@;2QMU@hvF@EAe07bIsr%P;ZV}(1oQ;HI-D^%B8}BI3*^Rj6 z{B~SQAN3;7I`a1yj(QFzkNG#d{}JL`hq=OgR1KXhApd&mcZqPTpKULb$NFuyDDWa` z|1Np93U3&iN880S%RN66xBPhj<$!R!4|~Mzaie&{{NjDsGQx4*b*gZjcbzR9uRphN zZbPzh;dS^n!tpx%mEytc@cpU%dsLsn!m(ZrCy&+nfY)axwckLV*}{=?fq1$&7-Y3sS@_#D4UC=~dk;ihbbpJu(=12X@jQa0)@1s1JEQApbz&@DC-A`A4~bG;#J%A}**(pO^SG`Nj(QFy{}$@^cHubB zzneUkzu60+o>Pc(zfY6rbMikc9P7yoRQc{X`0XZICh z0M8R=e}Qo9&tH)LJL>ma;iq|hek70eyVCppo4ECh{qwlH<16uIYV(&$U5meGR5;Ev zt2@X3f63h;)Y-x(H45HV-;yLrh)5kv_xI*|?|9<~d~*XYRX zP(Rdp$LZmG;9TJqYJ_$f!fX2z@=ne%uD5(#J%mR-uKwcrY*p}Q34hwc#@l$|TR#eX zy71v8LI?AlBhO!+=Q-hcEPP2kef){&JJSAmuiFR0TR7h$o_Z&QoIgwZ%3g=xg->-J zjSKg~ydY04;W+S4(EXe&az9p~KYY@TK> zr*Kq*c&nJ>`Flg*c)r<6IG%5Ia*lp+e%M3!sL*ZHUp#oec?Y%MMdKPLyt{kuCy$M5 zmXGTZ;x;b4zO+<0##<;Hi?=n^O~P@!+(sU&!zi!AIO1IA$H=pX{7(yq|5@^wf3y2n5@-J= z^88Bv&BFckGb$#J`J1is!c7SEH-&kQb6i?@1Lr3Z|Bd=RO*r~J(>d0+S>A6uX^(z8 z2uHuy65mVxUN0Q|-s~Lx9`Jr2l=kR%hH&(|koZ38cbV|IUY}LY(Qo%x!wtKs{eJT7 z7k;{X{ua+l_ndp*;raTVJWYio&qdCWr%FNS;5KUi2YE&dKgILhBc4(2c}ChFbTw}hYM?Ke6{{>|R+uhJg<{wW;KgGx_4T(>`|-}1uG@qVi~N59Qhha1wR zJ^F1c{A~ARl82Aq!NPIga;NZ0{^b5{@*jb7w78Fn!rOYk50S@?_gS9*IpUV*9e>?s zDS7-9Hf35V9PfV>lE?f9+`o%Bk9WUtjQ6OVFfUeTYhU%3Fo0v6+frHS8bAZ~fySQh^iZ=1+WlqRY;DflptI4`Xx9OFGl_<-WzY3SU>>pv}-y5R!h7;h``Sf1`{g6BHo zHs0pngna$Tb0UrRCgB+GZR9ckO7}lWoaZ-RIL5nDc&}Zd^8)8K-l~*mt#GVY8^~jM zs=N`#`vY;y)2DP8?{4x`BmaKk81LWYG5;v{SAHP)Fuylu2HC03Ex(bz86i(C;m^;a*Klkh+^ZJ;*;%IQGwn$YcKQYeUD+ zQTyKHSuXrm&siXzmF{_uIM3s^t{Iji^!izOb6uf&_q%Zbjd&exH@ znsDSlojm3r;Qq$MIsX;p=|lc5!jZo>dCb4o{ey|K|1R?Q(vTYGeZniGXcSE$kNL~L z9d3A%IQv(S$A6kPb%)i$o4Wrk@|b^^`-_OPe+PN`QGI?9j{JX+$NZbzfAp02O1$a( zR(Edm+n@Yr2uJ?<8;XgKy z_EJ9n#^YS)Hje`-XH(%@7zZxjyyC*(2zCiibA&i+5hGnoAU3ZLZpOHGZX z@n-XA{s!-+u11xKv%j|Rz2ApUE^u!1K7{&hCH&!_k1i#T^*h!3?M|Hgy+Jto9U=bm z?jI|Bs`H8B!Rw_@Q~R4K|Fgo^xaS4(SpGepzmPcRe_uHAe<{2}6z1a(=T^^KD9^vb zv0jy$7Vd|6?D$>?TA4WKIm@~E{UhwDJ2Vu&CTODz$YbMO>i+h`+22h(SWo&0U+Vr* zF?lS1gN>m+U5K-PAbGMV|4`wR zf+o71Jm#P3{`-itf4XoS7tfM^1oiuZ@af*~E99|$_jteSh;zT63P-=+i6869ZsAzR z{tyq=lM0UFymx#*46Ffh&VQkBjbB=i#<~i#V=bWv`Gn)LD3defVi9A+^P43Sm&i>)#xs&{N3diw& zFL})0U{k2`!^GJ?pFH^O8oS40;qb2@kNKy%e=TwLe@33Ml>cktSWkA4$NYQT|2uK^ zmz)tdiZ`1t<2Wu(c5d^27xi01xPQG(bQXE6-;N)eHGVyVIQQF5IQqRt{8&$}6+ScQ zqk-bVdNPjM-%a`N7moF08hI@LQqP}9obx{~9QjuZ$9nRabE{`I<@s7T){`CNu{`BJ z3IqO~IOjR((YR5(VIJ}NOikf3+I+|9OY~y9P7#D z$n%Ksd9}lMW;(Y#_fVeM!h71_<81+XEYBv-^AT~*^QCa)`AztT{X?GLom-xJDbGK` zQJlXz=ea;Q@^lcs0*AkAL^@Ss6ci}(z z?~Cd2?`Gkc-(vElj#KaV7vfz15>Fnk^9=GID?HolQ_(rbwa5K6h_k;# z0`DOl>(wp7+h>LexXrm;dz5mH7LNMgL!OrL5IcSz1~8l2&m_+R;WzqtmxyPndtM{X z{YK)vv<<9wXi=<~Tom zL3sNHq5T@?=(n2JVZHFryx)(-vwf`HGyXky;g9-K{oKQcr z8pk?(jC0J(7$5Hm#9PI8ZRvl1S5R-uzt&P|(7{az~k@{~1-I+4fv%`FZ$Od!tVoh`ijsiBj(T_hZJevv%Z z?;-DZ2XXHAX#boq>M+f}@90?PHr|EQZ$;q`g<(afkjMJ%y)E3(fjIZuLpavq0m88k z=LkP=We7Fdx#je)^h$L+UATV?Im#uEh9!}&v+aGXChCjax)Z@O^n$F{cQu{x~temfKA z`5H`~CFCD2yk5{pcaq2ab-oQZOdxK4tYcGzV;##EKi09O!fSZHuM=NNIo}c9&)a|C z9QDufoLh)<{l68C`u{=x7pUKVg`@tZo{0w^Z|HZY_gk4b*Z+b9-c~q{qaMPaDF_3; z*17G6%P8md!jbc4^4L7K-yS@ZsQruNd005k!ygwb!}tf)D8Qv2;={t999$p0$k&lf(> z`&~*N%b)N0HxjozyRNi~#NQQ0p4H^vA{?*ZZX=KROYaOF|3mFxBhS&##*O05dNYnX zAMYIN*dX_`A$q_=a%Pn$~jv2R0|z%_mC%b9C^;!#4YCy z{wC^N@)VMPk#N-WMe>-x&JUsAuZVLU{ucgLTA0Tp79Oti8tV5L;W+QA;2ibO@qRBR z&i!^2j{5f!j{4s%{7V1wvwNLe>NhCo1Hy6M^$2;aK07_Gf zc`vnJOP+(m>xSmhk&8l|QMc*tsYsmbcDi#L?_1J4yQ!JWmhd zo1FJ2kL6j}H*`K;_`MgEOx8rNFkINmpq$Hvv=#}M=< zX^(YvpYU2ft`nY%?;LMdf39sBlrb^B2`j_YV~ zs2}QI)xUSBq;sq1dz7=R@EKuPQ6=)&c#Aw|L*kb6=Src!Cgj;b{+7Z~&x^@p{>HmQ z$2Sw_I!qBhs!#Ng`Xbu(H!zvztg?nkBM`?`-GQo7CJdV{`aZh==o3& zOJ^MYmUeFQV*T#(e(O{F56E-Aa9?Jk3&qpL-w^F7?Xmv!6Yd}HiiVKK#*6jmLE%_` zo)nJt=Xv2+f8KI#b=XAX+9o zoz8Y{IX|SF=LyH_crD0dIV=4V2GE__e?*>4;m7-U2Z<-kJ#&cjcoz%DxZV(6)sM%w zo!huRrabQpzryo;N*)_mk>`p0gR)xZGQyE3O?aOl!#ve?Zh49*Pd(wt)0jM#r}3T; zv=g=eggiZjSNC!C70-0{3?t5Uo=Kih$v<0oUH2~_kLBFw{+Ecee+zl=nzX653CD5q z19{Bf<=4>h0pjd0|3av@)p;}JuOb}vNpo)VYyRc#KbJWBJCSD#`FjXQefpBe{FQzS z`G*l_|5FM4HQ~cXgmJ#%+{XJk<#|{5n9yzX5qT_6mghOr&pUKKKVCTY^OJ?+@%KXE z_fN27@%f2!yY>a;yiEA|RO=|Znmm@X$a9XO_FKu5Ega_?IpS%&H*}CM?QveWRCq1V z^8tByzCIU@`s@-u=JF8sXYzkZ`F|Ha#QXh+JXVM4p8wPr<16uo`MS!VRGsGB>ijkN z&lHaHkaNjn{(bJhg4!38r;BjZxwm+_>`TRqrV;15FP<#-TtMx&Q=V4Bao%;Qc#7Q9ojA|S4Z=V2&z)zJ|2yh8NBGsAe=2#b4vl{g zH#|k$`kj1n;Q7LFKJ#e;|6Ta;r-b?X%eh_iKe&vKTy9Ng`?l@DFydBE%_8xgGXX8Hu-%0I%CeI$>HAD0G`#3|LFfY^HQ)=a5&ihXz z=a%yq@;4Wbd2dY~%el|}ortqPOE~I$mvGd1mhf}@Mde)QmU9o~oF^Rf{v3HMXP3W1 zfmRXcdH;euzmor3;i&VE(Jnp|GWMjg=hPE+r_z!_czMZTllyztY`pv zEKj9_;f5K+IZvK&?9YpY<8fh=@HGEXks{}ob1&uGDjbgs+sR`&vpnaqt3rLuvyVI# zg{NDCcss>8_VXh5)FE!;Z8s;#8VSe#mLVMLXGiDAgY~n!@aCSUpLp=SskaF);h)bR zCw%hHVf<5sXVwp|CqJcpLa4*@!fz=Ep4Xfs|J$K?^tSLr&WprzMy=r4mC*h-;q|-@ zhY~!sUJX8*FWwL93;*t{Fkjt-H}x;~?d9CM+fVyRf8h`NxCWEQ_P549;K!-`@8p>y zyrO#+if6ieULnro+CZK^$X_JfKc*dRC6DFY=l&mwv;P#IXRCwxPxPEMh4=7zsplN^ zALPHcm@e({epXxI<=t~V@dGrjn}wrpBb?(n?ecdBI-WR>YbJUAB>!yTcztgHd8}^B z-Tw}?_qTpi9e*Gkp3lTn>7S6Z#OnWhzdcSk_S^G?XEh7QZ*%8X#)CAj*21yhUPhjl zafB?-a|g9QM4oZNQUCkJQ{9$n!V(Ulfl0_Eqwu>*l%kI$9~(E_&+qRD}b#w~25(F83FX$MNC9tNHJ~-R|6aJCbtVE!=Y1 zHjzA5w=B;&kJ^_c&vU|W4~KiSTs%eYd5yS@7r$5XzHod${AS_!-hdy3<9p-F6ozm% zUdvf4HLCbKMTHOcoYkD;_`>g!oFjaTpLDkrp5yO3Tu1z(xLwe#n$Bw(kB|<^Vym7eBNBdaKbAs?z2IK8i=U8W^ zyQePkR~`7aiJP0&YIk|(upyT3Pa_Ky}1o=4mxytDf!i)ZTmP>03Bk^g<+ zZw?NkkH}w|#`U>y)c+guq#iGh4E>gVGu+v(9Ydb-!cqS!&Qbs6?m3e<*QYsojwOF< z;i&&*93rGF$7Z2(`o7$J5oC}2G@qGz-EN7PI{D9h*CC_KV zTa^y;__cV7-17r*8!sM5{uGYKkt5fJ&anRAaio%PJdT|2+^TCiYlJw_g~FS9&hFyD zIzK@;*7-+;W1U|h9P9H+;radmvtD?{ZDGOPBE0_DVf;S`$K%~!!twmQ%v=Ah8=k*c z6@KNo(C!@JpLGp+S_;SSf?X4noe;r_q@E6*J<6^S#=dTMqSNO3n zhn&v|$LAFagujy+a&8pf*8d*rE8+N@$uGq1JOQ6I`IETq&kL^&Im^5q`mt-aAL2RT z3Bu=xW>F32*w5iPPud?kD(uiLgr8O_@QcNBwZHGyRrrw^q2s%RV||__yy%3`KG(U8 z>p0JDJX@iQlR^r*`p38|_eymr$g=1YBBOL44qs}dVdCK#Y@XJzZqUag&q#o~% z4)u9U+L!hA8-=%bzKwVV>h}lXoxwlgbu;%vmAdG~uuN`_XfpTXn5I^}KEig-sX;lHUwm4)Mcpt^I+S0(?UuXfTN`$-4koqW8*i2D+d zx@DB`k={PrIr`1=ekT#<{bZi-41W`Ex$vI;dE+AIRtL*-g7>>s_)zD65wApbEAj5( zdKz!%?T>Yi{6(JsENPFrH5A^$J?)5}Nd0yY-q+iAb&h@;`{z#YlJ*t6{e8l_I?pG5 z4)wcK_^sZ4rE~N<-TQrqIIquNlczrUcL=}M{lAdM)~kK)|A#pHE4&w^HotyKkuseu z9QkWFNB)ds?4I%WN)l&(d-61({2hfOe|Pd&{yg^&B+mZP%M{gd^u=!iT&Y=COlwyVitqb`_4#`&~yK%h|n5@Z3+_>bZDj;8VzB z4|UIG#Q((GqrzXyNa5%y@|b_6`{xrk|04gK$&13H2jd&#ZH@5hqr(I3`@(Nt9s1oW zd_#7~ze{+z8KM1=?}vV@l|Ax?*74(saDRA@Y7sv(Zof0!JvvYL9_MX{`%7A>jypNW z{xI*vaBDB&UH$dz>xDn>e@r%1c+2xc$9D+dzbn;kbg%GNi$ePch3|VQRAQ#^>jnk> zwD41E1kWPjb(;mgLij%aTQIRE3_9l~$&=ViYN z|Fmc5_n`1$ezJ4a2jO=-$w^NQFwX(0-9;U z@%L9x2yfOac;*XV=pUq5BK$)C-icR)SM&F$-V|QLzxQ&Z@KJug_nGjsTZcMq6aH%T zkn>03^*05+U-&ydzyAt9{r<2&AG0a+gZ=Hu%E5Dj@Ku{byK2Jg4-M_ZUK-Xlf5{+) z{AI7ydS@K1EBPJlI`gW+v6j_I;0=VI>etf~cw6DK7)W*4RX zzIIVZIP&|?Po_N99vq*0f(QBAiwC@;@Z-Gi-U)nwaJ>GLP5c;l*hP+TzZy+X;JLz) zGe3bZ6<*8xE=b^Oh1d4>#l&qbz_wGkUyb%9@I%6pzqFs&*v;k#FE1SLr&mqjwT0t& z$sk?^;p5Bp!jZpA0`DyxIR_>1VZzhA?=cB{yzm;{9`6HNK0MdAoARl>apYf~zzc*U z|GET@*Ok$4J?k{ywn}?&{A~i-zDGD-A3K!5OS;hdvwm?NkVYJ1if@kU2uIGw2|Qi6 zUya%)@Q%Xmxt49c6Zin(bwcwfn>Zc=?WP>z$Ui-S=L+|$QGNnnDjdgSK>}YZyuRlz zCXUBsyJ@FzTCsF=&!jZoyfo~O#{5uo)9^v?Y&O-^jq(3>a9G3HB&zeRY4!fz2aO7{Cz|(~z zfBOX9Q8@bUoxleONB(T$V3t2eIPy|4!k^ zzb}Cw5{~?({YjnO-~8a^g`aJm##_|{URyZMOEZY$Ik9=#3rGGg3B0#()12AGAmPZLmB7acNB*1yK2`YX-gj;S zpC|kbZ(m5fhBLcZCmi{U68Ki($iFjz?-7o*?@$6S=?~DB!*XJ+Nh4m;5FC-4Enkw2SwErgFRbA%)R^aP$O9QpGT_)_8ic5YOVz}E`*w+*9W z;_bvHw?1;I)Ng|IZ)}hYh2>aOCfjz2{=IslK*QNaHgd=}Z0^cee`FAGpJ;L$$dnkdI^d~Hq!*aIutZBs0ru=n; zBY)!ro-Q2u+b8gj!m)PrPT&KC<5e|Z8g5RUxo68I+JO}+1}34FWoX2|L< zI$J)xrfxTt7LNRt5_nbN$X_RcHxQ2crzh~X!cqTB;tesT_;QeN#2Zomb;6OqD1mPkj{G|l_#WYY+8-TC;3fUVeam4v{d6%(BYqy` zuOl4!8z=B|;mF@Ufp-*+*Is)k@BzZ{T4y%##*{xtIPy3i@b-non>(|Mb;6OqD1mPkj{G|l_#WZdcMm1-lK$qL<*=OCSJH^% zIke@kBOLh~C-8LP$lpGJcNC8Ehu#T%fN-2YWE018ddr_99Qmgw@Lb`@pP#^&3istV zDoEgKh5O+g6%%i1!F}5)9QpSp@I%6pzqCKF+WpNBUS2pJf2$_&+QRYpn?d|SgpV)V z3rGGg3B0#(g_X#w{vC} z?S&(MmjvEhIC2h3;KPLDwbwBTe7tbH)|p5A63U-19Ql_g@B-n;zb=7q5{~ovtqFX) zaEv$d4^CJ}>r{;eY%`5Pzjbm7R~K7n@>j{Ln7_yFO^pG~|2<S7u5jefPvA?1 zH}$>?68Ku-&Afdv@vA8RPT|PEFM%Htj{K#4N45K#AH2M99KTf)cx~Z0elv)7r2OrL zBY&3!-di|w4ocv|gyZiK#w76Z!tq(9JmQ@wf4*?!U!K4Vgd_jD1inc)9*?#r@a@9? z_g?34Dxj{^MG1VXaOB^a!1oBp`g16Om-HRpa#&8RKWW6Tq5O4( zBY)!ro-Q2u+b8gj!cqU;34DNX)IXbeSIVCw9Qmgw@Lb`@pP#^&3P=8e1in@{@)r~D zM)`LNNB(^Y{E%?uFYO;{wELSMyu5Hc_Eb&awS{A?&mi8N^0ya`{9O`wZ{f%}D1i?X zj`e3u0v|8Dt!K?6-h=Yz3rGIt3A{i!@~=zan}q-G_5TFET{xaEMAbuR%h!|gmllrv zl@fSW;mBVnfj1ED@uKtu-d4C@jWUV%qWpt|BY#!`A0r(3a}xMe;aER&6ZkygSU(Gi z_on>ogd=}Z0^cee`FAGpJ;Jg697^CN{lmeQ!*XK%Nh5wO<*y?g`5Pzjbm7R~K7n@> zUfcWboxleO$9S`eUq|_Kgd_j-1fDA#`STO_QsMaQY(WBFE4-FxEhgTF^6wOm{QDC4 zA>qhhIxR@;{^kcSFC1$})dXH!IF8i};+fImt-WyM?~=fK3rEgD34ECF>!YxZN#Ns! z-{9@@i1&477x}`Ge|Z8g5RUxo68I+Jcs*xp0^k1s=(->1*0Q?nM5_(EtGoL=93fO4Wi93I@%L1%ea_5}-hopalY6AwYnlQKMD}c+sL!3IqsHG{6-j z1SuLdO4X=Wts1pze0|TpXFqd)>sjmRTGOPTy>retCp&-JnIXsf1^kCkUEdwSKlqB? z8lHorKQ25$j{cPJG`at?lSo$hIypYCE*bw3#0RHk@(X^fD!fLH{)X@-`Mv%2+rkgX z{jXUg1LNDKe@K48kBx;-$k9I&enyVtxe&hOAD}J-9j+7CH)$OAA(xsWcb9Wt8R1!S z^yh_dlKZzUk)rTza{qESQa6tKwCik;qrWA*O^*Jq@I!K}|Gw~Ja@<~17S9Ke=dAMj{d0Mk-NOxK0HRA_B%)j$AAAG z+j+R3pEL6-raw>ar$-9Hi{$7m3$Ktr;)ZbNHQ{^YkM#39#$RmuyX5Ha3Gb7me<*xJ z{%wBW6XB=i-;UOA49~c}ABP2}QF8Rhg(t|-pAw!X$Kz*K_&PZrKTF2_O>*s8l*!Rw z6<#Ape?xea{3d_w+QJXW@8RbUgb&Ft`uStw6LP$soC!Z;_XlVpe93>n=%%^j9P{&& z!c*k;_VY8sv*i9i=NZWh-z5K}zwwL0x5+={=hw-Py*J1|?Y$+uO^*L=S6BEU`G@_2 z>kB_7|A?PIHU1L6M%>Aa+#mkPT=;?<>pyy1xKVd`w|#hw{O#eiNJ97u`8)jlobjqR zcakSZe?fSW9Gzw16>|UU??_Gf9=ZQ@YNTV_EfM_po4Vv5^+7%1ee!{yKNLP9f51w3 z@Fv1f$sg$FU;CFigNwT3>-ynQ|A7+x>;3$=@C5mT{QQ*gG&x@HW`(blf5vaWME+Ut zW%AE?uL`e`f8Nh;2yc@Av!CA3zA72u}SIAHN z{G9MS`B(h>g76|a9tX?9E9Cd{Ki7osk$;WOg9Q{?{HFESfgg42z{l44656GY6=MRkUn*Jd<`p3d25A$)}#$3JJhX8QBw=r0H_ zlB2UMyh4uSUlYDZj^p1k{u8FZOOF1Y@IE>Ehr&nXPx1Sn2tOs?Kx;ZYPB z9Q|YA6LR#=grAY$?)SYAzVz^Lg6pUU|J)J&7)cs`jW>6aB1eBlc$OUfdEuMn`29su z_%=Cye^EF7Q>MQ`j{cVLHaYsc!Vk&u_}LeJOpeFTsc}4qyQ?uHNB>;-f*k$PM}!B( zUEXaU9wU#1(;^AsE9Cd~^K-`cyt$J+Irayrs6{#w)D zB}acxc%K~oL*XNGfAd8q!cWQlkHP<3EsS=3uQUBoa`eZAC&w4c^>IiX8nJ;aPI@=Y?;Q`|LT~X(?26e|6KTj9R1Npg&TF3ciV@@$nX63e}%7*_1`ANz6n@xY29Q{?{HFESfgg41?Jlnz#$npAZ zV7zJihveuV3!jjqe5q?UJ;~#l!814GrVfv%w=#L9ekfT2(JWY<{pB27Nj^kf4{!Y_hCP#l& zc#RzW4dG349RIfP19BYyf$@FQKO{&0Sonk-{WIZb(uzqoBkO&`sczINyhx7DvhWJI z|8;kyCVY?F|G8A8WBeCPf0rEnJ>h+F^bduP$Zz-io(MlB$LpU+HoTzg`$f|qB}ac; zc!C`LDdA~yte>p#b#knqlJQ?M{bh3WSB2Ne(cci>B;WS?ZVNvk$K&U~c*pb)$ zHhI?1uN(gr)88ORe@l3q9Q|G4hvaxX=?gz5_kRu(nHv99(?26e|6KTj9R1O63peU6 z@3s$*k+1lDCxow%KiJRD89(smPV(gFF9&j{b)5COO`Zw1pp#P_=Ft&GvR0CSpN&*OSv%4b+}Hf z|D^HvhEuM6Pm!ZPBRorv{=D!_@*5-JS5f#j`AvR)-T3>wxswJt`dh-=5|ByxTrJM*fm;S|lNSg}mzL=Zs(W=1%hD z7yMX3c##~PW#JX_oBj4{!uQDU>F0Nhzu%iX>5^aYV?E)0a`X>{kH~TVod`cA$Nl%( zf6O;%yAb^I8@|zzRptnhVmtpAen-wYG4eJ_)vzbd>& zj{b)5CVAQKyDj{H{P}+V!1$r*ACjYgEPO(a{+aMIay%a`gfBfYjB_2X^FF>cY5W7; z+)0WY{Tbm|a`fkgZ<1sE6oqe-WBt^P|CZ@*kfXmPyiJb&uJA*0te?K{V{)vYsqx=7 z{WEg(&xJ3@(H~t8H|j3$whxbyWBnwAuaIN?r^VCBLn*@Cx~gpI;Nc zM~?R|9pk@a`n%-l?+NddFZpc^g^$Q@_46mfPstyI)+dE$T;K1)g3~BD`s2bAF9;WcvfH-tCI@%Ymgen5`LpMmis(?29f|5*5h z9Q`xlXXLl~eJ_MBJvp4(89=z6@E`49MgXN9kmKi$tS8UMKH zFO#FcD!fLH{)X@-dB*R%E&PD|QGWiw_`viJ$EY$Wy{- z*Y|s-KT3}NxbOry`cuNwXyhe`xhVUkN%I~`^{DAy6 zKYw6+X!?ib=pPH8kfVPl{EQsye<6HnBaCw$t`qA&Y5X&$KShrIjPNWu`t!m!$^FZl zNKyDUxqq6A)Qx}E^f$=S-xA&?M}JrNAvunJU-&UOj{ns7=S=^M9Q||Q3v%>FzbD+N zyS&>zJVuVkpM>xgayu{Y| zKS|?%WcpL&=+6kxlA}K_e3KmOrzm`z9P6iU{0pYPL5}{G@HRR6yTT92v3~l(kIAuq zrpCW$`e)?mp9^1*qd&SCZq!}gZ66*Z$NEVKUm?f($r&G;{yaJQ3&M-!=qwAbkYoMS zgzu4K{dA0f$@F*0(ccr^CrAHK_=p_qXCnNR9P20Y)G*rh{juqflA}K^JVB2Bl<+h; z)=yUWIyu%)$@rH|f0-QpRpB*q^f!bz$?^KFE&PBSuipm7PfY)i9Q|YA6LR#=grAY` z`F$^hFFh@s;5uCAYyJGB@vnGuCn<9DXM|_T(VrK-Nq)26cTxB@`91yoy752p=1v;q z=x+&clcT>Y{E!^$zc2il9P58-{7+5)j2!)Q;R|x~NBsk%yS&>zJVuW7pAf!6j`g22 zJ~91ya`YF37s=6C7G5Doe@*xvIr=-s|IGAv$ee z_|)_d$hU!k7FnXk3Tutor#${#T~IL5}{G@HRR6yTT92?|l3heoTJn$I7qdy}&OOF1$@J(_&einsqljHHTZv5{}e}f$TE#Yl)^mm0H zlE1_6yD$8h{GERO)c8M`{uw#?=fW4{=#M@#+^D;}+de!-{z$*?gzy#ejGvz~e$|^h z$&;hMAiPM9&a&_d`IG#!Ie^mob8-xJ;^NB>axh#c#GBK(vb>mUEq zU)T3fra$_u@CP{ha=iYj8~<0+-ylbSOL&_c{axXQ%5PjpEUko-rPxw9Q_&LS#tE}g>RChzbJg09Q}3U|84pkFe>mKzyS&>zJVuW7pAf!6j`g22 zzA*iHa`YF37s=6C7G5F8`l$)uBggvb82?|>-z7(XPk5gk{X^j+a`aDxpOT|LQVOG8 z-~TiHQF8Rhg(t|-pAw!X$NJ9-Unj@Ir^)@Yvkx}2yc=c@F5FCHNRIxo@CiBkXTs0OasOQiU%EYV?dw`c@D2Chr11;a2E%zNatvjJ zXUWl@7rsf3*TY5O+vIrvTQ`2gg|OXyZ;)fCCA>|J{;u#t@~`u|?h8LAPx$#$<9E5> zF*uo#V`wgXL5}{Y{}<)l<=yt-G4c~XkPyB?{uMtzXMD-+#DC?{kI3(Q{1<*oe&^%=kAw%@_1z7T!TBgThT_5# zi8;X1MYlg4jEWH2X1j-ib3EcsHnyGUO6COO{!7KLw< zh+F^bduP$d`T3MEEH=)?4Jc;RRjaJrNn4kCJ03E<8bw{*>@E`GQF&r;RRja*B~-DA0@|7TzG;U{VCyTa=iY`3STG3>(7$$uSI0gUna*;Rd|gY z{SDzw@|XG@w1pp#zs%1c7+*$Y&_5){&{+6{9Q`xlXXH5k3*k#Y8bk$OuETZW_$Q6u zACbYF6gh@6!n5S)&kNrq_scs{6uwRFuV$of{1!w8{S9&qwS>3H(ccw*NS+Gz>Aw2H zkI8Qfr$?s7zYdYX*o+)QbKwhe^haM1?#Nx=4N2p-A~KkhBF9ihc$OUf zdEuMnc>P%vzDUQIeoT(npHt)CfXJYKMvkGm z@C7;gqdyjGEckMlciV@@$XBk-3SJioUm?fq&z$iUL*h2F6o}4El%U z7#a(okfVPl{EQs^3*k$Z@PNAx*NOh5@!JsT=8$73BRorv{=D!_a`YF4ZY{E!^4ANsViSSc$yx)oZ__eEj?e_g9X(uJen2e$x2E5gCl7$T5@=o+U?rUicEG1L;?CP#l) z_#rv|9-uG$n0(D2|EcjuA~G18kz;5sd_j)>Xf@oCyS&>zJVyR--;)r&LjDLpKW99H z$Y3l_j-i6^A~`zC!Ykw}zNaR9kNnQZf8&orWU#F+Ifi<|`{d{!3LlZ<^V^B=Q*wNM z8+mDX#a-W{5gDA1l4B??JVB2Bl<+h;-cMzPuaiG4%#M_dKL(M(SeYC{RpB*q^f!bz z$#3;NZQ%#x5AyQ|#@7%Tj19>#G!{M~NB>Ot8983RErc(RDkr>#g)_%^wJxQo<{KMs*We}f!DE#Yl)^mm0HlCOk^H_{h=OpeE& zsqx1nGT7FP97A*A3v%>FUmk|J%e(EvW8_#r3E?Z`SU)-ASwsf=%9CTLAiPM9&a&_d z`7^?+8L0{1Bj57#JI22ik-=D(978?feRA{Bcj7Q&Za5l(O&t`pB+N#jpIWH2X1j-ib3EIIn~!Z*nu z@B53wx5@E&OWpW)ATroigB(LG;casCcZDC4KhpR2g&&h={QRl$Cn7Q!n~`H^E_^|b z{^%>i9l6W9?Zac__xC*s;Va~~`1v{G>xc}-^5hsQ2rrVOvn;$qezWhX3Ev~Xr=Q<3 z{v<>OV_k9#^@R7y(LWSEB7cDInFv26f1sZqc~yAE^*tGp!TBgThT_5#9<3Blu z3c`!z=qwAbkYoMSgzu4K{dA1~03sv7<3BludcynU=pPCnk$+<({F(?qCCA?zM_v!&Dun;h$>Zv0t@46Z|i978SPZF2N?g&&fmzc2il9Q{+{KZwYne@2d>x$p%! z`lCM`-k|RCZu{^UIr%d#eoDR?-mHCEq_2enyVZ zPZq+LUK?)Eb+}G^ev&kPJ0gQQDRK;DglEaopBKJK{s4b{i^8|bAL!@Tjo*RDV5~uo zp_cGAIr_W856SWSqrUKCa{T^iYWznK8T8M{F*FyxAV+`nb>V?>mv`HT$H;FDr$rLN zSI8ga=jV)XBQhAvlVhkLyhx7DvhWJ|H~5~K@ICSsKfh!AIfx9#y5tz@3Gb7me<*xJ z{wUuw5q?VkXg@#l`tXeFdoCh_^HFjP#f2xx(Vr5YCdc~E3STG3`Y#!O9wLMOGC78- z!fWK{ZwPOa-x?mqNL%;;IoAKcco~twwua;w8VjG0qkks+jQsJwe<6IS5l(O&t~2ZB zCyhTJk-=Ds977r5S#tE}g>RB${S<|7lVknVjsGYjgZ>6NhFZegF-w=km%e(EvW8_#r3E?Z`SU)-AJBSSSl_$qgL3oiI zon_$_@*Bge8L0{1Bggvb7=IxmgKc%mG1L>@CrAHK_=x<$zJDV8l>8xne&mhe8Q1q? zhz!n0$uSfco*+kmN_d(apXXjS>%{s=8h&yWzlLXOv~IpbAC2K&mBW2hj!NRH03@Cx~3!>bvo3Ev}s zoS)w@j{k;%8|spyzbCv;j{c$W5&6@7&qVks`7`|d$j^pnTp#|M3QnTr=#L9ekfT2( zJWcN3o>-!cA5 zLNB9Q_61Me_}O7g&gmvE*bv`L{sqh&&`sczIh0n>+A9-6C<}UBH508@H?)&4y6XfV$GyZx+2HVP!V`xKofgGJB;bn5XZm9~d zk>mBuzVQYkgZ>UVhAs>5k)wYgd`OPh17qP6a=acmH~t1hy4$klzJ<^C&M|aRc$^&l zN#QB-o5S5jGQzXu_w@6(jK2|)!B~kLLp#E&dr3ZIeR>U-wG7vy+7w*2<+g0AlpB7^fuaty5s&yb@(Cp=I71m9l}UL^kx zKY!Qw&muAytCM5slJFKe`a8nAxmRZ3r)rqq8KuOpfDU6<#C9@!vPzL}bw4A;-{V z;XQKn4}=fN@%%LwJ|V~R*SYbxAky77?{we7$9?A*x+pwOj{cNr%mB)@`wBRN5dr3ZIc<{m+Fj z$g%#H_rojV`dWw#&L_z+v?@G9j{cnRJURLc!i(hS-!=YrL%S+wPmc9}V*DM54Em?!7`iHaPLBS_yMm1cU+(g5`|v0^)_+`hf*k9A&Glb0*Z;yN-}e@T7s>JWy}QPL0g*v}og71#gty4i-x1y=$Nje_yibn%?}_nWL}buE zCCAWJ;d65IN7}*0f-iS@w|#h&{MKu;g3p14C&=;san1NIAu`xjjvPZ9!VBc+ED0}@ zWBpf!*T}K{_lkC&$nw;Vp9XcZ7Gz@p`f+yifkkzW>DdyAc_TP02BIRrs77{gGb^ zcjPYbwhxbzf1~e-3r~>a_F6Ok9z+J)%8_GeLwJE4oh9LAa;*QV@ESSR|Gx1qB7^=8 zIfgC^?~$W_Abdz3^T&TId_sP2KmXkLdlBizI^hII&M|aRc$^&lN#QAS^kjr*$?p>h zzqX9O50Sx8i5x>a!mH%yuM2OGt&x_)m_ZE5gU*=${Iokv}aG ze$9n1$iLsuU;gFrjO)9M$l!dE97C(ZGvw&c3D1+??0X8ri{yCywrl+T7yL$olR7zu zE(vduqrW4(Oa1`A>z?pF`2+p@6XU;e;d=j+979)y&&kmr`IT^+?(%N?@F@BH{jTG} z6Xdt}`D@01)9u86<;XF#A-q72&XVvlIo3~Ac#RzEXW#fCB7^JDA;-{V;XQKn4}=fN zv3|zFC*)W^=f*#PNOv3jYIs99a*m;k!sF!VPYO?wWBp`=XUVaCwv7K4B7^19Q{+_GjjCLg)hj_zkCp05!cs4 zWN-#7ogY!vp z46O>!kfT2*JWr12uY&L*IiA0EjeiW0L4TbbLzjfN$kE>s-X(uYco-u+;eGO|pMPTf z&(A+H z{%J%8V*_#wT@gMeNB>m#jQq~Wf8h)AJ0Jhw7hVz9_j`y8&L_z+v?@G9j{cnRJUP}+ zL3ok;wlF)gYy9^S8I0A*F?30IiyZwO;azgPe&`ABljHTniSZ#KgZ?QwhOP>qlcPWK z>*0ZNmv`HTN6E2%;=&W;SU+pVKZD3%UpaCNZ3r)rqq8KuOnzf{H6vBwHS(MM{C(q} zMPxA6A;-{V;XQKn4}=fN)4pdcd_w+kKmXkL=Md?}E{78wImggN;c;^GCxxfT@%)t$ zo+Zcg*Ou`shzy!bC0FZ~P004Ej6d7`iOHM~?o1@F6++ z$HFJ%=s!39MMS#W@;BYL@NwTchAs+^lcPT=JVpKu;qD?C;aTz(KYz>k7?HtPi5x>a z!mH%yuM2OG-|l-_!rSC``1wc1zl6wOY(S2oE5gU*=${Iok>mb27rr3J`R*2NBf?Z@HY8l z{QM*1e}>3lY(S2oE5gU*=${Iok>mK!g)hi){Fi?_ydtje&k-4%Pm*J3Rd|LR{W;-z zavcAH@FF>m|E}@BKxEKgC&$nw;Vp9XcZ7Gz(bE&&CtnK>d*sCU6p_K$lpI4>h0n>+ zAL)fVa+i18heyfrco-L+AitOIUo-xfhz!PZn{OJkrljHH{#P|%6LI0E-Lsx~*$8L&zkYSLu9b&965$Igcr!sSrT3*e?@q8B30ov@>lx#`^Ntsk-=Dp97C6d z_sG#d5I!V-hVK~*pOA0)`RB&}0g-O(D4gKPIfgC@kCUT6DLh4v_g@*|S#rGI*fM?< zkwJ5b978+8tK{gf3vZA=Ej(P2mhd+D_xt%r#{UtK!PtNtLsx{4$r^VyZiaO#{U_SL4TbbLzjfN$kE>s z-X*_pco-u+;eB$vUOF*;hR9%BQ*sPl6+S0Nf8@hqn7h2&K0Hc}{ZuaQ5(&)+xxuZRrBI^-C-EWAgK{(9L zMOwn!Wxv2cRxc8>mw z!sF!VPYO?w)Pm-g5Rd|LR{W;-z@|XJcP!L`uf0>`ZYdmWD z>*VOaB)mnA{*Lf2IgWo%c%K}{|HSw`O#hS|{a1z0$mL98^4$7?~tSavhW@``Uk>?VXT?kGRrawvU#@*Md z@C-TnbHelFc>XO2FOsi^IgwrC54gc&a8f5n|0Urqa`bnEcgb=5d&2wVIQ}QbZwR_? z&xO}vN`8m;tHS5x&++pkp9;6%cD&oKQRa`ayo-XllE9j2BJ+ zfE@i-gpbLWeE(GVjJ)FK&xJ3@U+m{Ee>yzl`krn2ljP`M6`mnq^4re|&yzpf&)+uw zL#Ahk96h_j>*VOUB)mnA)3nqSYW!ZYOf{qm;q=bHX4a&&GB-yui;uJAhf;4a}6xFozq{s}+-(D?IA{}DO* zkA+_$NB@cNDfxy!{#S+1$-l?XkNH2;aeZaezf6w)72&Jo=wB0_BhUDr4dDgyNBQ{` zcTE32Ir`x$uJSXEz^yksSTY!jt3!-?J(_L;eXrf7AGnnf@(u zbZ!gZAxHnN@H#o3e=iAdk>mbyX#7Q{|A-v@$HK3WqyI$slpN1rSB1~X@%$CL65bH5 zuVVU_$$kg`55Gu` z{$=4w^0)b(RpA-(mY=_A{AH$piyWQX!gt8gzbm{>KJY!4gty2);pZP3f4S*DB1iwR z@GIo#KM_79$Me@!;d64_Ut)h4UJ=)~Yxml^p$R!gJ(!{@M^;Ajk7p#rP{s z|1LTD_k>>}NB_R?4*7;(50{1a$iK(W9~pn8=|3Sy|Ech+Jy(U#$v@%e$G#AraeZ~uzf6w) z72&Jo=wB0_Baiu>4dDgyd;9qn+7Lm`j^Skzao5<9Q|v;bL6=HZU`@s{EepngdF{+!mpB}|6F+FkFVeEZojYgJr{+?$?JZ8 z+W60y{xx#+uM6KGNB@@a5;@*~?Fg@uC52--Op}5{31E}mxU+EAMATpg=feg;^%J~f0OCoB1h-8@EvmW z?+UMzzsT?4lJFLJ#m_%9{$|sEM2`Mr;aAAfepfd!sq08{EVGkUk^>wzf6w) z72&Jo=wB0_Bgfk9UnNKXx$wwWuHWu%zpwT?xF|eMUib6U#@}Z8*T~VoE_{O={aeCI|AZXcl*WqxhOnNj`fo^ z{`01PjU4^!!Z*m#za_jxj`g!6yh@Js(=^^T{rlwTKM;PI9Q{Ya2jsW=^>9V_nEVbu z|IGL=nErEe^e_F{_1oRehhHQ||FZBT`HjA3Rd|N{CO?1E_%E9NEpl{j3*R9}|E};l z`J;W$CE+dd$N2e&#(&B5ACaT~Sojrk^q&ZylE2RPTopbif4!d{`}6RO>+6{QWpebd z2wx>f|C;a|`3HT^hVTOUk)K~N{>!F+mmK|j!Y`4de_wcq{9V4MZ~RwG&oMcAM#4|X z(Q_*ND*5Am&$;l(UxX7}hwIGx`3d6(rhkPT{b}KAXefULkJRU9! zPm<&DFl+ohrhlCr{hPwK$kDkie1|;lcd#qGPJTZ>ziqs0`VYv_e<=Kj9R0__uaJLt zB>XxNJ|%yOpT98vUemwym*E80?Hv6v;mhRcUlG1aj`g!9JV%c8Q#AfQ)4xrA!C&8s z@Lh8B?+L#|{wBZuec>JQH~aa0g&aLK;d|uhX$s#bzuoWp zK=@_yJN*2i@!z=NdjE(V{S)D*jZQ%#x=sy&GM1H&PITn6}{0={VX8Z%D z|BM{{3*k$r;RfA2w;lAygfEk0ova97CCB>78~-iSze$e%qVR3!gtBhzbE_> zIr_WCf7|pQlB2&b{Fr>n_m701kmK`>Q{h+1@%cvdudm23i*=nPYYio zNB_F;4RZ9CjsK46uaKj^CVY<^{Y~NfIa`cacpO8P-_nZp9O8z`QKROG~ zxW12?{unv>6T(->(VrH+M*d*mvo3st{2_jR+4#pye}x?VHQ{^Y=x++&Cr|mF1L2p+ zv3`ceKW_R*K5D9Q{S%+vMo42;U|DfM3rogUgmf7@!vQ7eRA{w=)8y#S3STG3&*&zb%SIr?Y9&&big5We(}*Kc>X-{{~gzu62mr0SP@O^Us^cv|IADR9>Ir@jf zN95?A2tOr%q+dU0!q3Swet!I)udjzcGW`j1^rwWU$AtL9~=Lo>7S6JeX zW%3O_KVy7s`m^Nd&kNrqM}JZHHaYq$!gtBh-!lFs)88gXe^>Y+Ir{s;kI5h4kLO7E z3Hby4{JHTzHvJ27^hf_CyrBEp&4hu`{$HV%-zUf8XV3VF>F<-He<*xJj{b@8Q*x}IGvVjtSU>T9y}lm4V)_&0=uZhx zlcPT?e4QNYXH)nVIo40r_@9{m8aetK!kgsiZwo&lf0e&K9tuAqulf07<9}-UC*_zC%rpFcPL7p8wfj{fL8yrBEp&4h%}J~jPCa&(r3SIE&{6TU}|_0tr-PmcA|Gya#RzfX?-q3{to`X|Cq$yBu9T+ z_yPG{{qa8(enfsZKYwie)bvlt(LWP@Mvnf4@TLC<1Kf7qeph@?O!zW6Zm*2-zc&3@ za`fkgZ<3?GD14jzslLA=e3$%betygN-23i;Ugq=m1Mf631;7@wK`A~`zC!YkzHuL<8HU-mm_ z3g0Kczn|YT{&%LoPmcbf@DVxsC&Ew3(SIiVoE-h}^Xu#3?@fP#9Q`TbX>#;ug|CyZ z`t`6We2e^Hety;XKbZa+IrY{$u>A>7S6Je!Biim;5F_zh(TNOn;jk z{axXQ#;ug|Cy>eb1)wE%Mj+`BmfpX8LR7=x+#blB2&Z{D2&< ze-4Eok>mBx*!bM^Psq_f6MjaH{)ON`8O89?pcHli%X!$N%5;_3+=OKS7TEl<+h;`m@5<$fyCSU;P>x5%-6s>bhO`fKFq zZwPOaqrWZufE=%X4uv0)2H&xzbpKZ9Q}Ra$K>cA2|po6 z|J?Y!O#gx${n5LH=iGNUA08t|e?s^Q`7^`i6G;nSBY&2kUoajs{Y7$gmW5Zy(O(n3 zNB&*Drzw1&{JZ`9p7DE|{ysVShr&nX=${BbCExV#{mz7+lRwqZkKa8kbKmb{`V-{n zPYF+xqdzNro&0J3cy0>cBL99rziRxxroTpx{)X@-Ir`he56EBYdk%#kk-yB(9~+OG z{s}qyXTs0O(Z3MB6b-lNzPtTC$@j#BFOxsn&(9dYpXtw%qdzZvlN|j;;oIaT-%}C3 zOMbhb-!lF%)88gXe^>Y+Ir{s;kI5^(XC(ZD{KbC$-1s+}{slSuqc?`<+;=x09wSG8 zLih^#vwcs___vszJURAT5MCrlPg!_{9LKXJe2*N*vtvAM`n%-l?+NddqkkxTM2_Qm z)%e3r&zu}Rk(b<#eU_kyp?^lG6$=~ni zPleCOKkDbtg)hiI=I7(@j@{>vk2l9Z7X0kK+;R6W4X^#2y!JixyZZC)ByAkqbd)oG zcYofUY#R4(9j{5rI6gylgvT4#gU?Ex*WI_^%lSR7oeRG;{dwmXjdzUWJ(iIIi02rKhjDNlHL*q%~1LL&Cy$c+>c|8}As;89y}s1mgqa z-(h@Y{E5b=#@CIX8OM9OYs3DD(jB)aoB1*0-)TH)Ja0U09G{)I;hgaeGk??g_ZTl3 z|6b!2j7R*F zs5|~!#$(3uS(+P88pmg5&eO(!(1HKT87~5Z(@o=eE$oI%#(&7nuNePf<8|XD<4xnY z8}Asu!}y``A2B{KzHNMD{5i&_#-D5a%sBqrhu4Ph7EW@#UNZh;#w*5OWV~*?V!UY_@4eh`$M}z%`G>||Vtin{YJ6n;rN*bm z@tKwzJ~RGuGe6>A6uRTTYdmKB6~>dsUuisT{8h$t#%snmjsJx4lJTE3UNQb^<8|Y8 z<4xnQG2Su$Q^pUC|FrRe@jc@s>H2W82;e=UB;8ff6jQ?_|F^98E+fkH2w?5OU8fEc*XcH8Lu1f z7;hT?W#b*=zheB*_^%ot7(XyRGX87Er^erH{LJ`!jN{FuJI-C>G5;ph`Fo8gjla)$ z+W4;<&l$gLeAD>*jhBr7hVhE=-!xt~erUXD`~${2#(&HBq4D1~J}}-hJ~IA0#;3-A z*Z7(74;sgtc6XeQjK}T~{^0yW#*@ZBY&>oJBgS*a`^Gnof7E!%_{WS_jDOsC-T1(G z)A%QhcZ`41_@VJn86OxwHa;@`Y2#Dlzi0f+`0pFXha>Jd4~@qzhCev}jPa!L&l*n~ z|D5rh@hiqRjsJo1lJUb_ z8t)kYE8~a8ziND7{M7i!_+J~J8vh&PXU6~5c;uep5AOK?|GMr6+{yX>Mh?c)Yu?UMW35zg<-#**tZO`BP zy3Vevv$MzjI`6$dpZngudpqks6}Suj9oz$71^2%R;X(Kh@G$&GcohB;c8x)*6pu|8{mT5UoAG=1Gm3=YPb(>f7Q_N0K60CCkXEh55qTuN8y{p z<8T)|3GV_=!?%EE;a%Z*xctpPGq56D{x+cTGJI>)slvB`%YU>nBiFQ>!vpYc@F2W9JPh9f9)<4+kHbCiB)kVa4c`f#h3^c{!+XMu@Lk|# zcrSPrzAN0Zg_+gnJbU3T_-=3ye0R7Hz6U%2?+p*a`@qBSJ>gOKUhp{F2T#KL!qf16 z@GN|9cply#UW5;Tm*M-stMGl{@=Gs6ez>b^W3@DPsr$h_@crRFxcuK`Qy~DC|D$X? z2tN>Y!tjIOQTV~|I6MGP!ViI`;fKPr@WbGF_#k)@emJ}gKLTEb9|?DCX=bCj{kOqg z@T1@!_|b45{1|uuJ{TT^9}5q|kAp|y$HU|BAUp{_0iK4R2+zV#g6H8w;6?b!@G^WT zyb3=B?%1j|{~@>wek$ApKMn4KpAHYehrxsJGvHzPneZrF{%@t}JPr>dpM(#Gr{N>u zS@_xTJbWa)2tNm2hL3_*;pf5~Tes#v0(Zej!#(ix;6C{I@Bn-aJP02P55q5jN8uO3 z)=)R^>Bx~HU9~?3w{IK z1HTdOgWm)Xz^B54@M-Wc{APF*ehWMfPr{S%Tj6Q=ZSXAoc6c5>9bSabfS2KSz^m{( z;f`%v^Phsd;CI12@VntY_&x9dd?q{yp9K%Y?}bO<_rc@vG&~8vAD)Ik0MEkz2hYPF zgcsqn;br(k@GAUaxO|w&PzLVWuC-nsfqUSO!hP_^-~sp?co6X9O8vZmq3x5WlhtGu<;q%~S__OdT{5iN|`_???;4b*{aF6m{%^!F8;4dH_fWHV2 zDo@%vVde5WvnYH%>co{xKS||#+4^btOQ@5DzYNdAUx63ld3YJV0A7W^3U_pC&Hrm~ z7knYy1AiUvQ!eumfWLu!5WWZ=Rxax$s(hxM&p5n*I!WcyPg=RGmn?iS>g3^X!i(^? z;AQyR@GATrxSVLw(7SL~_ttuO5AJ~%;Xe5L@BsV+co6;}JPcm~kHVM2%5hhOdQ3;lIM;@ZaD``0wyEyavz0|A6P=9oB2kmHAqPuLm!~JHo5*4d4z> zv!=Prjo>c06Yha;3irV~!2|Hl@St+pKZoI)BOisk;Bj~tcv894Ps6(+pM`G;&%?KZ z7nMu>GQ1n|Rd{!}qlcq$=}`YV6z+nb0{6f}a3B0scmO^O9#lTA*@hzwKLh!w@-u8c z4nGt5q;jdBhM$FeR=L#A!^6lI;ltr&_y~9vem2~(Q*$64>Q^J-F8Dcc4}28d2R|1c zfJfj#_-J?-ejYpuKOY{4kAWxQW8rD|1@Nr$E_VIq;TIxbgh%0J_&9hKei7WUb8G&` z!(H$Ra1Z=qxDS2_JOIBG9#k&l4Z~x|N8y*jZxC8a@f0gB!>@!F;a9=S z@Ho7xT*fPZ=)r9NlaY7zY^|58;U4%ka36dMJOIBI9)w>955upAN8t&09DV~l3BM7Z zhTjCw!l%OX@M-WO{APF=eha(`Pr~It9hv#R74F)lHUGE4J@DJ%KKOKa06qgAgx>)V z!|#Mg;VF0=eiu9mzZ;&0-viIWXTtOFS@0tKUU(UPAG``r!{tABnfbpT?y^tl#vg!t z;19xm@Y(PH{2_P{{xCcY&%mSbN8oYzqwpmBF?bq22cCsL4$s4%fEVFU!prb1yb6B` z?%1`poj(nC!JmP9;B(=6fFC$-uzXGo+m-kg1-q!q^{LJP}hYOxZ9glM9$ERH0R|&uupiU6}Dm)B-4IYIr zgva5p!;|ng;A!|GcotrO=i!UtMddONW%!%OSK)8L9lN#W-}nrff93aE_rTvq9iMXP zC!k!`OA!7J>V)C%!lUr_;Bj~no`k;-Ps2ZeXW<{h^YA6`B77;l4F3pTg?|ip?B1IH z65It}2KT@}f&1W}!UOQ-@F4s%co_aUJPQ8;9#<~wJqa%(pN6l1XO+u#m{%^_VG;f% z>XemBKUL+j9m;=xHqW#Cdu^^gTI*#c>U-c{!+r2?-~srz@F2Vb55vEMN8zjBarpP} zBz!eI4gUe2h5rc8!+(Mo;Z=AUz6M@}{|tBZZq4&Aa2I?n+ynm=?t}jZ55Rwi2jMk% z82$%53jY%xhyMjn!q>sm@W0_%_&@MG{9kwx?pVJ$hvsV;-T_{P^SsKAKCSuZ`HEd| zo(I?i=lOMgaGtj|0O$E&gK(Z_H4NwZOQUd}7c>s%`8Jbqp2so`=lLPCaGrND59j#| zi*Og_xeV_Duflm=JI9`_`RDoKTyUO;%>(E8&3tg4H!PrB-Ukc9d7iGYa(N#t3g>yW z;>x9d67Iu1q?JqkEW9uBdF4{S25Tk!D+8e9pi7<+xBDE4)M3F+mB=X=f7I_*=xynx3~SuFSfS>%B6mr^5yn+7#^*E zf0Df&Q7)fdFd1_({h06NGXXJ!^^3UtjwjjVhMV2h=N+4nQa<1QJ~*v>q4kXNPWJta zyzeQ4E?+2)VYv#d>SL!$o)Gy*++4>&k z=i547<=^hz{CS^pspD6^-@(m%Q2DR}njTXAnf0*p?`@rk^1rOd;pX>!XEn<^63Vx> z&s9m~@|rNET#kLS@KN;|x7zwS<$u}RdF66UUr?T~`;;>LLe#G)m-bvZ? z&Egp9yOm3Qk8-K+RW9`daPz*OJ*;)KDPLsgEvWnh>mlVM?RcW_+v?v-eKQtwF)`yG zH*VEGf2;gU>j~u(Z2dIc99Jy1`HXUpU0+${huQr}PWce)MYwt1FWLJoDVNu5W#tPu zXf{+)zR0>9Ynie(()a;6h7o@`(5xfJ2F9g?S>m?i6Sp7FaLBlgZ)k${;zi!Lj`1+ugGx4BrI#h;qA|cSPZvA|F%U!!C=% zJ0YJ?ZV$H{NqA@EQ_6jISsE^LU>0SRyKFuS-`twH$|<)Wzjx%}Qp4m6%Do2bmm*w_ zHH?>(+rt}287}MGT@R!8Q!x=jjt8u(tj0he?`;C*OU*GT6QOH?oMi$ zMNZ{|ZQcc!$Fy1GR(_|=d*Jph!^RS?ayc&Y!R5Ky{D5EiAX`5G-@}@@YEv#_3&Lfa zHTjToc^wgk%RboTBg(@D>z6289z(`s%B7z;+#dRyxFez5-_ZK@50`zsS(H*P_0w?s z5~5KlqkNsMpM~2)`Noo*a(OPy!|fq{BVSN1`^qA`zr9a$RZ@PGT~>w8(#hoF8=xy(-Z z%ltU(i$=5kpNhOw`G5O=_-V+ymG5AedElob?^Q1I>4OhL-mhHdCjgiChRu()Dc{A` z3c}As{g84wHVwn&y)pA+5#=(rC_Ie%G3BG|vN(J=@(Ja#ze>VKAfHk$uSL`Fvysmz zm)DkA_(Aws=7xgR3rJpK1f_zQ6TAYW77Qarmvs zCzQ+MB?-R``IK@wen`V_M?RzcWxFg3pN@P^xzx|YXCPltF7=CWdCoCER#GnY%kVo< zzoJ~~SK%q-YszK*9i5sXv;E(Nyi>WXUl;stjx`w7DDMLwil`U%7DLq4Kh<}(UUBOg;f(JqU_??*nNeBgS`g-Q4W$fuO=W|yVm z|3f~bd>6Yc3x5##oN}q3htEd7pnRZRR)jxtKH4se!n4T7l*{pX9R3vY3FXpH68<#uDdo~n8vYFO8RgPX7CsmGoN{@* zFDT#1E-S*HMZTn5j`zy&=a8=`m-(r}bI8|}OFs^~A(`#}dE}kSN7!X9_zTFp zl^<=FdEhT1?^Q0_rw=|KdB5`g?Xmz|UgMfYZORX@`5;`LGtHuq@}V{#hQDIXTt$=* zu*;(Gyft$bQ{LMyi^CTnpHME_TN3^%@+sv3yDSZV4f%|6IX=w77b2fiF56ok{yOpn z<+6V(!rwr?q}<+gl;MkzuPB%8rwT71UsEpqJ2r2I%=W(+d8cxDK61g|MBc4j>U-dC zA@5Z#^W%fRjl5sE9gZUae+T(C zy;b2Q<9`Umzb*F8L_DjC@S_1iLH_Ux9o=xy*kO{w4A${`{{KMUX#?VtcftQe-mN@g zmwDiSA@5Z#{rlkSkoPOMHyr`^-^jNqmwXWZ5Aq@9(tjBKFY*!PgYB{?yz$|B>oMgr z-Z;F2nQVJWD3`}?622btDdqC`O2gMjKBIhD$L1Yp;T@6BDVO?r_y))ql-rw*B78&S zOUn1L^H7FwgnUK$zBXTlJCUy`m;N1Hn?Gox8zb*jE{|UqTt1^}D!7%){=oy^6!pEz zW&h@bcS7E;eD`MC|L^Y+bVj}ndE@f>E(qTY`H=D#Z2d5NbL1n+WxP?i3;CFGna?=9 z3-Sr&vOi41w?ICn{6yP-8r~K8jB@Ee3*Qp?oO04I;Eyj!{KuRQSWk@qT>{(bOn$orKa zZ2JkoyCdJGT*elJ?|^(rx%3l;?}&Uv`GK~dDBOd5Ou6g};_x2GCzQ+fnS}3zd`fwL z+fN$4Gx8bbvVCUZJ(15Tm-nyo@LiBEC?90|DZ+apUsB%7=F9M1k*_E}-{z}uFY-0z zl6TlQT1|8}ni~7gM6FvgY5hS;d>$< zQvToZKYTCbBg*aJr6UUWAsUs-W*#u2X3PKA@5W^ z-p-E;zCZGAujb*0BVSOy zgYBmXKLYuZayh;&!;eJ1qFlyXg|{JJQ!e9mY}0JaM2|w=sa(eEf**~%Te*za13w0N zuW}i$4?Y-qzjFI>#u0!Yi+r2%+wA-Y;m08#QZBC-!tmpfk0_UZqVOQ{G3Anv!%sjy zp zuPB%LRd@*bnsUiI+|6;D=&8s%l}kS^xO_&^RB$Voya#?d>U)(--UlCsykEKG1MoAD zZ&NPEt3mjg$cL0m{V@D2=c6?IY~(Y_ z<@qQJmvcy%^_x@P(_sCQho6J`1?BrRW=eQ_AK2hctXV@)_j=?Dm<3%Q;TWqMY*m zZ9Wgb81)OvPqFzTT;5|ai%QDnv(9DsrKn#~p0o9<@EGzn<#*Y6@XuXe4BFVKM21P`H*s{ABJCrd_=iCexvX> z@-gKj?EJ^!laWs--`D1o@T-weDVOah4ZjBYjB?q2vhXR$=akF#lZRi6d_lR4w+O!u z`I2(Um*LkVUr}yvI;!vl@-^kMJvg>+POOREfV@+=JYT!uHzMy=9j&V|kZ)5i{RiPUBOg*Oub0E{Tab?^m-oOFjv| z4f&MvzIJ}n@Y|8kD3|`T@af3sluJGjpMiWqx%6Lz-+_Edx%6L#--&!hxvZ}$JcWEs z`G4Dgx8_8d=v~M=mCJZt@Vk+BE0^(l;P)W!RW9{?@R`W_mCNyP06q)(HsvzjApBnB zL(1jx7>3`6d_=kQABCrpk13b_ThzuM8gwf#SWyi>WnzH`AJ zMc%Dk)|UtV81i1_C)xS&!RH|FS1#LI0RA}gZOUbP3&Nj3KBQb8zhU^3$VZe*KT&uV z`IvI)Ck}rK`Gj)mCkcNV`IPcA?0lx-&mf;sF8M5cF7i3$ay*}h&qKbTe5P#w@Mn=P zDVN7r8U7sd73JsJ`c-%i`I_>LZQfy5go!?nyi>Ux&%4@jw{m&E#RGo<^}WhvygvAg z$orKiZU2FGyiK{xf3O`7DW7fYhvD!;x_BcD+|!RE8@SCG#sm&bb^o=3i*e4MRcgfBq8q+A~FW%#SeSCq^4Q-!~Vd`-DL zUK~3%8#B>`$UBwGA>Oew6_2EkasGVybE4L-mQF8 zv#i4de;;|Ta+!Z0`~&3u$|WCwe~5gWa(TZx2w#GHNcjjy^Ad(HMLwcj_9s#JN65#N zOFwb=$H*s?OFv0?3Hg+A=_d_ehI~f3?9a3CPms?km+dnT{}lOxa{KWEM-jdp`I2&Z zzpD)Y4Ec(3sb7VEj(knI)OYl7G%hCk1@cbi{$|YKf|rqZE4TmM#^HglK;El-lCAH9 ze~G+b`C^+7z`sJiO}WfZ5WW)mkaC%yF#K!eBg*aW#Sw*ngM3VRZN26I;_z>gPbio9 zNy010r z3jY!Ln(~cgnSGAUr{dgtMHAGuPMJohPHF_ z8#6Ud|A@`osjn`-`Mu!gLg*WuUz^GwBv2c<@H4nzB%fLluQ3% zxC{A+a_K(`?}B_xx%3}z#}mq>|0KLC>Zg=T|7rM^$Y+#G|5^A}$mf(x|M_;jpj`Sd z!n>h z{(bOa$orL#v-Jb*c$;#0ehd(%dH*Ebjz^S_vi(HiXQF;gx%3}z#}mq>|0Mh@ z)K4jw{?qMvM!EE#g@;i;r@V_DZyr7z`GRseo-D#gAYW20^~>e5ew)q5;bW0cC|_XnN%#fGr{H-PPGX>?cev9yNs9#bp>$eQQ2>FU~SzlH7c;su!B`<&U!fgK& zkayZ0vbd~Y7yM%6-O8uiiSxiOLEfue)~^qKDe`{hvVH^Yc$;!rzd?8m^+U>K{f6O} zAso*FYh#laNm-mwXz21@al?vVODhE0NDBzss)QJp3x; z3(95v7U6N^OUh;amfP`)a#_Ds_+-?tDVO6J$F9wRnC<*(<2AOd*<%|%EhTXZu@t^Z%5v(T>AIGrz7uG zF8%x9Gm!TykK0BA@H>!iQ!f1k;dde*Qa;+&55rT)N0iI{HVVHB`IvI)Cl0?G`Gj)m zCkej?`IK_$Ck>y8d`9^QJKijO7VBMyHN`GoRw?Rb;$`N*e~Z*22v_)ExVl*{oB` zk&h|=#Lj;l{s!_1<+A-G;fs(@DIa6&r{M+UGs-*Jd=|bK`J8gu9`fyYLAh)XMfjVj zUs5jPEyLeJzM_1F?Z4WN*OcFH^A7t!Hrv0cFYZ+SxXruZZ=)Z#a+x1bJML93^W$sB z{mSL@7y>mQ~&ya6Z zKE~D$!aqkoq`Z^Ohv8o!A5kuk_h>sFQ!bD9IJ}Jd3FR{0Bzy((Ddn<1Ot<41<+9() zw&OYFkK6gl!@op71?4h7#df@;T;`|Tj#re+{;&#{*Py1=n(_^8|BgMI- zA5m_n*Aaz(k9Y#wWocPbxfw;vb$SLEHw zZ?p5`f&YfQSGm02^ud2e-mg4t`w75n$hRq%`a$>~$cL26@kSW_C-M>Hl8?gwLO!Nk z<|htchkQc0^q++PjeJVE%ugEr5Aqr1Qa=m-7x|oW$>-q?`#XQL>I=$cev0r8$d{B$ zz6@Uv`HJ!Zc6+PB*GImlT=owRU-Jje=F|~+r}9fXHghic2FSaW%kzZ?z9I5n<%ih* zeejKt_bWfy<^ymi@@>kcpCEi=R00PWfrJeje^ZzM%YQn=itxbccp?*a9IGc~Q<1yvZe;n>Z{e*JqKiQ6_luQ3f;qkcuX9M4qY{gJOJm%O82bKqwCAAr15 zxx7C8aPwAv13PEt>Ie9S@Q$wL4O4$3`1WwSYilg+2j3X^qu~ENch#4N;hQ3VDO_I5 zn#H%kJ0t%PT=s=#@k?+!#Kuo8f!l8z{yn@)Lz-W@*c)aZWZ!R=>>$l}yTkjy<^K$s z#e?A<PlI0sm(Nm}#kazTAv<68;hVD)_JPIK1<&%^RlA$?%@=tKkR0uYsQkp8`K0el7fZ z_;v7m;n&0G!4vTJ;5Wd(f!_%K8-5eKn>~0k^Dq^D5PTZ^WcbbS3*ooGuY)JyY51-1 zm*Ka;KZ4&5ciMwI)Bkk12R;LSBK!{cdGI^oGvO)tv+%p%@51kfe*?b<{ttX6d@Fm9 zYQ{ASzBl|{_|fqD;3MH__!Rj4@cHlu;2*;O2VVt$5Z=KaOq>2^!?%S$1m6$-Fgys) zz$5TS;8(#Ph2H^x49?G)%z-aL{&DyU_!Dq`uH#Ag_Pv`o%sgb_{oqf*kAgo99|L~| zehqvs{BHO>_*3v_;ryJybMP;a&%u9#KM&umPxFQu?+fr=@E73+!so+>!C!)34u2W` z82lCZLUjm;3fDZ_%itI@K4~6!#{;Df-i@!fPV)63;sELi@wbpX1rg(cY~MV zhrw6CPlJC6p8)>~J{7(azD>X84b#up@IB$*z>kH03m*foz^A~!gWm&R1%Da-J$xB_ zHT*aD4{+Ds%^PN1Kf?RKe}W$lufm7H*TBcae}>-({{{X4d@cNW_^6rO>1g1-Xq z4F3qe8NBnpt?_OS?+JIo4~BPvhu~Yl$HTkAZ-j3NpADD)b7MMu8NN00OX1tVH}SW| z<%aiw%V(5K@?iLO$cNzD!>7T!!5@Zqhkpy-0p4xDR-Ze<_knxh7sGqNr^0uFKMda) zo`?5@e+=IR{yV%Ee6#&q{qG9j6Yhl{2j2~T0ep9O0=@_QK6r0<4&Dd848AA)H~3!g z&Ih!{<%0*{ec>T^KX@FzH~emRfA~}I0q_ERANWf6zVLN$KfLR}*0}bA?+M=@ekA+= z_?d9|Y?rBg8T>%xXTT4FXW<9K7r_JYFW`s3H$Jd6u0!D-_+jvU;e+7E!4HR@13v;j z34SE}c6b~7QTS2t1@NQcCHOJ$pWuVx8y?h}hhyQr;m5%bgC7q+4IYG#gP#CTz)ysK z1wRRX^1-b>hrq|cPljIy9}1rZKL!3AJOqCiek%NH_-XKU@YCU41Fimt!FPwB0Y3zO zCOiZ`3w|Ly48IOO96k#^0zMahHvDb)NcdOqbKvVA;%Hn9je>6nKNsE)9)S;okA{zj zp9jAQem;C2T+UTy8hjf*7WuE>7r_67UkLAVXk)mIL(eGO3m*qR7=95v1RoE-5IzBZ zJ^W($z3@xm3*eW+SHffPO%7{~>oRx`_(ZrLemVSj_$2r!_!aOg;8((Dz^{V80*}M1 z@X7Fv2DQd@HGFsYHSlBMQ{dy_*TNr!Uk6_bzaG9Co`A1^c&pDF;M>7(gb#q<1Ro5a z3Xj02!LNef48Ie83;YRq68<{;R`_!GZSddWx5GC(qBRfG;k&?Rzz4$bfS&@t6Mi8) z1-}k{7kn1{ZungIJ@B{SGvQytXTkq~-wW?@WNRMogL~m=_`&e|;X~mMz%PLR4?Y|I zApB+cZ1__6L-3#A55s%4wZ@f!9|(U0J_PfSR)_9+W?*)GbJ{Ue1J`z3;ek1%@`2XO~!C!+v5B~)I0{j>Fi}3D8x5hOe z-XH!F`~>*R@QdKDz;A%(;d9^%;IF}7g)fJ{244q%9p3er*0|n)_l7Tm4}}-tW8sV8 zQ{ZpH?}NVue-{2W{2ll^@Kx}4;f}$ralHrM8eW7CfWHqP4F3RrHvB{QMEDZ;ZSbY= zr{N#L7sEe>uYi}}9gb~{cNyFb{{+4l{8RXm@a6E~@Xz3v!9R!J4*vrF1iTC{z*oS3 zgntR|c3f+`U%~ssSHh2je+|DB{tbMS<6HH=h5O(Y_?htU;8(&|!S8~956{9^!{34b z0AB_F5$+DQ`u_>O7rY8T0=@%5>9ljR+1pHU{BKU9c74YBTf52<-E+@3c z`v-gvc!%|x8T0iR_g+0AB>Z5dQEft$w2L5_}wdE&L+*rlD4y@$jAC6X3_eFNTkWUjom< zFNGK2F?i@#20KW?U6g&=J44(`y!>@)r zPH**j4SXB;6!^aIYvJd>uY=zXzaIW9JOO_fegnJ)zY*>p*6RNz_+Id-@Z;gr;G^I- z!ykp;0)G{rgs+C*3h#7AtIyluLHO|SHn~A_0Meec^7;; z_}%aW;rGCYz-Pj*h0lV|gx?E)27Vv>BX}DA2mF5cj%T&T^#FWd_=E7r;j`h3;19t+ zgFg)4G~Bx1416c}Bk=v;kHUw+AA?^7p99apABQi4KLM}8pM-BZ+|jt0L$NG;Ap9x# zN${uP=fR(WPlnHhr{MG8ufm^&FM~e^uflWijYhP_^*p>U`~~>Y@E76d!C!(;hQAEI z8~zG>Av_QN6utod5ByblkF#6jdJTRwd?9=|{B`*K@HgNuz!$+kfiH%yfxijgWMr$) zx8MWdZ^H+}-+`YEe-}Ox{vP}VcoF_S{C#)@{sH`7_=oWB=d{MP1U?YH6n+x?Blvmn zkKvQyC3p(H4E`ki6Zlg2r||VhwfbKU?*{)2J`nx|{3Li8J_f!5ekc4(_!IE2;IG41 z!k5FphW`Qo2EOCDt?_;fKNenrKM4O0-XYSevkKlF{yn@ud^P+S_z&|4aGt-VADriD89$~~hv#Ft z5zh0j%!c#)DzCzM9+hQqo-buBoaaU9GPczZ&wt{D|G)E`T-eIJH*$5fb-z5X$bE30Kcoofc|umfc|MSh$F=J7ydV3(dA^RJaGq!58aU67 z@jp1vYf*&rd=ynU&m*zJMXf%0zKFqao)@B-b~rlJznQm*+-hALKV_rVZIAudJXAJl zu_FNA5FUo3j3W+r+V9O(+J0~9Z*0FeS9$xrakg28Z)(49T$#q}7nASQ_^$cI1MdtE zz&C@3;hV$ba2Grc?*h-mw}6-7UEz(!>$gq+Tf#jC>KAjhRpYznmjHZgco@D7JPvom z)9`KKdH8nlGQ1mH_7!IFiCFQT^_wB%-I3o7z5~1sz9T#W_rMeI9`Fo&CwKwAGyHwH z=|{GqD!eE1u8z$cW?Z|#eehoJ{otm4U%M;>_aZ+WZt{oNWpVg!$lm}rdHXh?BLm+Z z`2u_ocm>`Y?z9hnGu}S%E^u?d_G!h@8@?yyF-0v0kXXe8D zSuE`fCu1Lz|H)p?XsD0*=Eh6`S3$+)?6)z9|m6s9|Z4apFGUC4u=nf z9|0c*KN3C(-UgouKMFn{J{Z0nek^<)-2SSwv9z0gk~94ukNiM*5Izik0(=tuMEFd& z{S{4P>3q2T)knjZ!|ks!8omxL`x3LDn|(4i{o7v=H1Y%C_O1Gc4};sc-Wxs%ep*AC zUuMGXTgZ(C^WpX_+lDWP+qXy?z7Bq7vvlKYH+#@v`nPWZHaq|iH>CL`3?B}U!$-i= z@U!80_(*seehyrofJ~pG;2!(LWc*xs03Lyd;iKVk_<8U&{Cs#GJ_cTf+m{H9rQgBL z{^2?MGfsODX8OOtnz{1A?IC|-XL-@v$Q{g86qs_ydvIs@S*Ke1Q+OZ{><+~l{m&zB?N7dMj4FJs{* zf3VF@g`4_Ic5UWoz)k)bo1Y6edHMT5FTqXza+_ZcH~Fo5*T2*+U&BrQ0h@Q)7a=Bl zi3!?^7k;T={kkvQ)ER1@pMvlh@)O{f!KcF~!e_xv{ZY35eE8+aFNaTpe+@TvF0yqx zc4>ypc;#5nNN2doUupBb;a8fVy$pbx{LMBWf?p-!`t@+Q$-iRrad;g08{j7Yp3P_A zlaVjLuZGL{`pkH*fjhTo-Y`A|?uB0qZ-ZY4kHD{oC*TQq27Uv)0KXAlf!_po+84d1 z|EcgUa5HaZJ8!+=(~utwzZrfq+|*fP>r8;(g8X!N5U6NjL-XOcBL6zv;nR^H44(l%8E)zvZtF~d-+}ye_?_@sa8qZr%mX}y z{OfR&pC@pwI=|XFDfmms-w!wW4)*oieE7@AFNePZUkA^_yKUFJVdiH6d?5T)_%Qfu z@JaB6@R{(};j`gpT%GN>7Q){^ekFVnyyN!G8>asPyeE7yybs*m@3!`S+u&~^AA!FG z9|t#ecCmGm@VAlA!ry@x;qSti!A1G~2Lf+H8dBga} z@Bq97KMHQ@-zxI}Uxs`F{s}w-{}f(;FNas)pTV7`iTcI#|9RuP<`*yg3wRs63_k&G zzMW;q6@{-rJ_-L4o`rt}FTz*Cm%+`qbL{=r;9n!}-m!VZjQ1OO54ic!mA1}6__xR( z4mbI#&4=L?sTv&wv zg?tsh4({5idBcqBZ@3Ts4}3qkxnHln-w^y?Q^0+?+M=kJ_x=c{8+fDFYo_G;2R;IfIHzC_{Q)8d=q#DzA4<;HFN=)+xicL*CJ=HLmU98^cYVm9~x--VOOScz5^- za8svar{?`d>BwJ3uSdJvdO||B6&hE(j z;d{VC@ZRtkybnAD-xHpL?*%Wxeee}<)Bkn0f5&c(_8Z4(eUbOT`@sY7z2RZF{BFcl zj>88apN8)P&%^hHm*IZ6WA|47`@ws{_lFOH9{?W-9|%vt4}@pn2f+*QgW(l;0PftQ z)&C)IFZ@t=8~iZ1oDbPN9tXh_$R7^Rz>k0z;77tM@HV)!cdP%S;9mIA@HY4{@CbY` zJOMuzo`D|+FTjt7SKvXovrnu46X0I>iSWK~^EgU%YW{o>eiHJh!cG1mn~%YVAfJMt z49~%b!b|W|;5B#%?%uOC-c#Xz_-XJE{B(E>J`A3Mp8?Oo&xDuYXTfXmFxBjG9dIq)2O6ubmK7hZ!$;BH^5|Iu(i{5*IFem*<~9|KRp$HH^) z3*aUAh430Y3U~Ky^*;{ohhGE_!N5QC44pf zDtM>8Tm8r3KKNvK5PmiMRJfUkt?WF+;MX8O8E*1DY(5R2g8U4v z-l>0Uyw}5f!xQkq@EhP`;5WjP@SEUS_*8fiJ`G-l-wbyRX!U;!+y_s>gYaA7QTT1} zB>Z-G7Cs$bgwKFi;dj7Y`?UJM6Yhhj;6eCZ@F@IlcoKdOJPV%*FT!WRtMGf_u6)9@htes~oA06Yo*AN(%3+5Q7|`_I82M7{){4X?o;g1h~#aXk!|^B9}`lDXfA zz25-x8RWz8N8oYzqwqBRF?b$62VRCh4tMO=>i-G22mT~H0MEk1@TcH$_|xzQ;m^Pe z@VW5S@Og08{;mF>h5O*o!GrJ|d?fsN_!Q;#WxFEd3G z!h^Cuhc88b0o>&0+WboRN62?PxHYbi;ho{8PTtn(4KE=-0B-U{n-9U4As>T(0#Cs| zh3DYQ;U)NI@EZJcxI54q?-y`CybKS)SHOqE&3NVWzH#`M$lm}r`HG#N4E!tP3-Fcj z3jAxh^N@Pc`o-*rzkzpwoBLg7@7D+a7Ww_)Cf{ST`j`481g{`J9B%S`Y(5VE4*4{E z6?`H5d-zKDYIw&(8*Mel`vbfu{73j8_)qYW@G5)?d<}dW+>G}SJKhZZXXKxPoBXjh z|2F&=m{wI1ZDq9c*_!_R>q0yq61VEYflMt6?I!oZ!BL5lOTeBxa;`l z&l#El-xhA_53=?B@H>zX!S95};3;?teiu9kzZ+hH-vh6~XTrM$TjQDq9|*q}J`8>z z{2aKMhaq+zrohw4PlKEMNSmJnzaRN|aFf4C)+77@&M|4eV(VAnk0HMXZt@+w*1yy* zt`nQrCOQXsIX|``li$MT`y>B2@*(&W@EH6_cnY3{&xbz+Uk-m7z7GBjyxU2wam|Gf zgwKN?4mac7#g2C*{8{9uz@LLZ2+zS6!k>q~12^|Oplh@5)$kXP?=++}t{36G;q&1E z_)GAx@?OodjtTIWk)IBK1wL1K($*;`m-myG!}F-KPPz2sI=MAoli$nM?+IUkI(^_~ zJ`cC^IT-#b@+ZSheyGh)fb;yESHMkvq|K+`3sFA@e;vL6Zt7fW>y+VdATKBOF|-Ko z8Cr+>#ZUp>AHEnqM7hj!1pX%S3HV#^jPey*p(?>enD-Y-$dr(F6Oq+GWD z5S-^(jloxGalkE68sJH~EdWZ07pI zzeD~&xXEv4^TXh)ke>wq9zGMk8a^NX1AICBNBBDUPw;NTTH~$42g29Dhrxe_p944J z?PJF~1^x^2)8Hn5pv}*LuSI?y+~iNN`6B#RtZj zCjhS@ABO({kHi0jr{RCWAAy_uP1^e{z}F#Pf&UF(12=WjwvOw}`i=U>xn}qXxvspOLH(P}Be6!2oJJfs4%X)hkYwLF!UcXVlm^wVqZErZwb2|WT>h!mDhQLjJoGDtrMBqFx?l`!qBj@j!3O9NC zuyUl~Jdf@pa8oB}`zgRpUiw)M=XrO(hMPKJTgNe?exrUd^JDVT&z5kWr?)%Y)EQ&z z41}A!^b>^ltGirIg_}B)Y@G>klb3!HaGnSFR=BB?uywLL^iI?MAlEr6Nmvw%2_Lh;Xy`_KpK|AyRc$L%84x@uh${dN%{Ne z){=Tl9&auYGg2<~8wEd-=l_;u^VES88GYB0V;HNxw@o{zPB18O@1%9-Uvif>ftAxq z%+_dVIa11|4c>*r2=wg*@C^;SVxw3?cN+3G7?W_wI-ouc@_P6mL%B6Y zz)N92pEN+naS3dGq1+FgkTYz40PWE>58M-Ig3nFTK0qh~G9R>a0@#W27Vv9`uL7TT zs1tgIdIVzLhK|s7`2I%yHR|h79|YSHl-EL*Cb3|ca_Tz|avuCIBd^(j27KLt25QGc zc?Qs%#(oWXE$osJ>lDx*adN;3J%G(u#3ICpOb331Vo|dN1kiGuf$Hs{t3hljS<^g>5$_UoRp1lh za~1|X@E)*T4cSW6*P!kP8!Z|u9Hx_2K&J%e}FCy^=8!D!2bexYt#q9 zSA}rcq{D_B&lbX;9BhA}UITe0xHV+MAe%$mf{2+6*(&IVBi1;S$??(`^{cSc2R{LM zHqakF9MlOVfcrq!1N<85N#M=!9St8sWxy)rGXp+dptD2S7G+J?tVP`fc4JU~0DcO# z)1g;K*%bOQD9=Ug-6#|K%ra&d>hIuN3%ekc$6<_}02P#H!>0i8^r0g(1pZS=JCGCl z1at$YK(-flmhjsJ+sBY?0bc;Sm59>=$U*rx{6k@P9rbnaF^2s)$mhZSAnLoJ4+cK~ znKgJ88gM@v%Ne;{LcJ0E3HW;;8a6i2A4Pc&@*tE2eFpe3=r(|#1D{1>7@!Rm zU@xuPp!^$tg|r?3+cq@LP{g?hIR`ujapJ%Uc>qz6Pe%T)Au9unfW5#O=v=_R0mIOb zv#`rXxe4+dlsD2oZb3Ue(2fi05#V>BBV-QwJJ=IyMQ!~Nryc5l!K)&agl zsW0)dqPdfD3d-l9+X26=sQ;yLZ$lOcSu$kt;3D*6KWtAT=6Be%h1?G19pH6n?<$}Q zn?B$V;j01NLFmSyo(6wH3*g70d5lC|8>pi?qJIpZK0q;SY~g2&_7+q96Zl5LCJ{Ib z8zJ<|077Eus=zwzs$&Vg?^-~{`F;9sDB1yrI=$PKbvh}Q`@l%U=Ny3ME;foH>JBIL!eIfb%5&Ly%l220!Gppm!XeFozP5bzZ5ZCsLTO<`wQO( z(65BP1}K4y5C2WDlTsDRO_0Td->0#;u=@e~Bao>A9_V{4;+jBz7coDgd_@`nycP7H zAX9_xCqU>6kc1egfO9B210!Kmjo5@@ASYA}jD@TLv9%FrIB5&AEY!_m^B$Olm=nM! zfuy)5waT+4SeBOgz`t|yP%z| z;NKwAh3#vUJHoyn+I<3^LgPIG-whq1L9o39-8=Z|KvqI+wu660Jq|X@qS6pntWLiQBGLGbC0_ViKSPTPC{ z*)x=5;Tr_IdnmiY=P2q0DC49iPNPc@WAyY5pr9i-J9&Ww398eHQfXAWNgZtQO~B>N5s{J5nL|4#eklVti58{7?|1QV~ zorSzV>S1h^$%p+`;5(2EnDeYP%OPb5K45eK6W0v;;T= zJ4;|3+PVxILjMqlP#f6ogp5z^ePFkn>XsvpH?W7+Gr)VpZWMSI#L|M_NyOknrVcw_ z)PsOL=uBxmNhANuKdSJRr5-fKeA+)*UCXj;bE;Ii26_DdXmE=*<=H30#+;4;(f6U_ zF3)xc#(_`>ZF^CR+;>vFNG7*MG>0zmvj-Man;s;P4E;h`MW#L$<)iQ&E)(kyWUt{r zispEZ>h@9I8~G?f7XUt6rXRtyYy^K@U>F8;1h|xzAf~O%SPi2&+EcEH@o|E_4soW! zNg4jrP+y344x;UOw0#2_u$jhs1AkLm4x%<%@GYZdVqO5f4dSNKu{;f*fhY$;Hx&4e zvOVlKQ9beD!R9P-azS|r{8ytsh{k-6Seu}m512u|8a8hsBUFX@FW7a2&taK(?V+Cy z`yDh!Blt1Y^}v_V{E7bn_)94tJ_}&82eNp?T7h~p>iV>;H#F86)CbDMxC8q~up15# zY7f2^vOvU`MRR%yUnR(&0t0EA&k-XL@=?GL*&PBg{=hE~`s1*jgZ3uLw6_{D&O`qQ zb~@1cqCO5F)P}aFg_tjC*^tJb1^$)xh1e=VABniuDF3AXL@rBesMrCAVfO{TYBcx# zh(C?SHInfSrEN~9vWegoz*Oo-VlO9uKxv5QK>PI@^-#oo0!ZlvVwpkT2QoLAyrueJ z>MN}eLZObza%p>i;Fl>AvmMF>kd1)e9pys!bfN(aTC_2c_OBQ89cY=FN>~EgQb*qm zX^u++Sw$LR4!HDBVf`PuVjJXfqhxX$s>>r{X8=B8o8i$znrfpL4+Gk zTlkb9UqV|bC*`%YyZ~(z+JU+w%43n!D#RMkisk;jj9lALjR5U!fZuu4_n_TNsEcSW zAt=|vb`t6rXii-rlcmRyN5F>A6xf|a*%4)TDkE}bnj zkm=_|;sjcQ*o$F*fW~#CIXXbr6POJ70mK+dV|zmHDU+)%^b-*G0k9qRk zbE(~MC`JM8k)s#l`$0!YmvRf*wdYXR%D~qY-Bw+86-+WEnZJ-$(v{I?Kdyr{%>oAJzib`>6j#czl7}!8_ z+Dy5XjNfhORneDjkm&+rVKWvnX40UgGX3O2w-lHS5UPUxX7Dq#PGoJV{Qx>QIj-Z$77BESALmNbSe-wNM-@SOxZ z0gY!#Ik5|&v1EPv!G0F}hN7+g;I>d60#sz$SqJ$q*o_4U&8NCjw)&sH6XKg!AXOx?%oH%HkK9*DjUe}x>R_t|-EA7LTE<3d(ga;D z#=#ivyrFj4;AQBSJZgsRPC9O4*i^u;3ifYlUP@@gA2LG6sogP@lWE&ZH10rJ{{-84 zkVU|zFLGTdC&$Ay9*HTXMX;69c$6)u%@7ECp`HT14LR+i?HS04`wTvVsh-5T+M=DI z$p5E|elH!LTdMAJPNUu0U_Esg;=uWg?d^G8POY|jc}kN z`Z5h|8qoYKXy0UGbdt%ZC)(4MGbVm;2tYfX5vN(keja2IG&YI(h~_eqw)39Wmm>!+ z#6AtVIqV#%ocIumg8m?6zhwF@LVY*2ONU+^c9p2lM_EdLsJ@?6K)El?ah*&&qH0Bb z&moTs)K}{I9Q|sFqV0QATcRh_335JockqX> zze4rl5-t136EPP;A0abF1iEhNy+HKgOmbFahmP0l$fO)-vO9k+$gwy$<5^r~af_KK|&@vAqPHDb3}# zOncJi@@Pzd2rAKcbHtO&7rq0izc+k7psWqPP9~=fv>oEcCpI$mxybh+U;)2M zD(@>3zh&_w@-RUk)M-9Hz(aw2#61Q7w$NE4UT>8D(RkCL?<$keVYDTt<3!?LK>t)> zJ4I@PdM?VDfD?QpVS9_(pM}ht#wEU=QGbj2O85{m0iQz0BMxO#$o$}Y1^7U1Hquy> zF^!NPK#cE*byX7O|NglK8KHcsG0L5h6QS;qrK7FK;G1ZhMDB<&$f9k6V zjYVuUX&>HFzloF^!S_DO7hrP+_J4uCunh*|X}Lpc#1 z2P_b4Cwv}4?uW809c&S&7WJDnCt~*z^|%%`MD8MEL+X=c>RZu9FPR*OJ`Z&vjpL8< z5!fFBZ%>q<@yKsAAf=&*u@QPYoXj`WFQURhjLp=}6m@SnWI}dGPL5CDvri@_iR}iT zJHQ2*e2M%o>Mn@U8M@yz)~yyc?GW$(MNZT{2>u)y+Wp$ zUVuMj?#THlV1qfK1-mZb-CNi`K)hv$#f7|v=1XD_T1ssP%Jlt;O!+2!713L&n}l`= zjYcdB@UgUwH>f`b+$CD}&kEQc1{P7-R@f%V8(suhn&xPC)d?WlaTI3|P(}dg*m2Fh84BQ6o9fU8Touo~S zg_JyCzZCW7(3?Q`9`O&+wzW|vG)Kmsm0>OIA(z22@rcV|Ab`q>U?+ghPx$E29EnW|%Jq;FN{3ELV`y97k>^la z?n3RPHiX}$eIn&K@V_U=rk9Kjv6CeSR3-r5k;i74{0pRI8gDmjJY?dWLHRt*_oqyo zn(%8)^Od%<6tOj6^8&n7#x_W5K=~`^eK1a|!283_4&|RMY$Bz3wUCqQe6;II+pa=x zUlC_LxG!yUGR;>k$G4>@9sP4e`wM0IENior$~|Cn6Y+1LEkcu8^nE&&N5bYj&4bv@ zKtC3vZVvn9G%q6Wg?N2Ycb18BA2KOr(Ri-#w}*cii9z)tGI7pRJE@;5>UQwiLUZVY z{NDnfAU_X27wz?vX-5OHo-#4gWpw|fLBXwL$_=#rsk9AW_)kFGXxI#Ze*@}cWwxIe zEq90BkM_4C%41|~`qLa7Xv|mO*C3kU~IgWL%<1EsKCL-YCseT7Uv zBt|lSjA>Z|d>L)GH_F}Nvl=lhW%817lN86J&6`xH2fm!PGo0p4RCf?#2<(Dr&i!b- zR*KNoPlMfU#Ho|%!wtyZ zAYNB0TY$V`;ZJBJ%|RLUp0tf^D37AKw}mVQ^_kS(fbvwdB}B|{pf%!tBf(H6_joxD z937sMW70Yf*MYg>%opM&L4rWY74jL5iYk8X=rEjEQ7R)6c#4$-9O2L|7Q&%!>SgP= ztwhtzgxdH8E{+x9oRYv(FXA(B_yQ9qU%(TFcj0>}@l^zj*ue>pnfSfbIqJsB zVn!vE365gQY`s!BVbZ9SX5X#CwF>Y#i?>hU?GenK1t0OgO_A3K>6Do=68NG5nz?GQ=)jIZE6<7F`k& zO~n3Up$5l`X{E!*b%~+>`p7O~9S0`Lk>_UYR;I%2_Yn%?HBHn-qUgj(QL#X%Y|QWk zL;2ofF5{0DQym#TKU|<5EpivA`ile{fk;chi1>^+T-nA;tUo#+$z&>5z~KZidJK;* zfSVRp8VChqZ6|CNK8F!v$dfn=7=dhqZFIZ54Y|T&4}9Q`WwRv zGgntE>Pj3i(^PO{Rpo_%$M^R)$iH5Q%X~qs7EaJShRbEbMKBSHc=;ChQ&Ojkdzxtr znSc^3AzUOz(>#9_9*4Qkj}Y>8I6O>|JVwN{vc(T7o*;qe&zSJ}9F+)FCc!IeBIl4X z&!LqdE}ZGX9E(aVKwOco0Dr^haZW_JF#=w@2VV%NthsfrLgD^rUip2!8VOlZq5hi?YYPe9X ze61P!%Tu>tMA>3B2JHw{93vU+(;QKhC|pUPYTB94yht_K5T}!%mD<^qlg|^iVw9L@ z4RMi%XtVMDRzf9zAxD5j98E^)+8GaL1ZXcB&mmH{7n$jd7!x0(#c+fikx)s5Ar^~F zGV&cl+;s$<85Mqs5E6l|@vyRBVWzS;p6|eO;My=;0gr<*Gf~mj6bIvOkT%ztLv|h^ zM=XdCYceKcbhH(h&*3s|f=H2&?4kmHQLnWs39UH87@^7mf#Xm_&QReB8LfB$m)R8$ z6E71nCy?RA?c@oSnJ7`dkQ<>Se8CZD1v3H>voAcBrDsg^+Vi6~raoH?jhCbn{3%hVd%o1&pF;_{`A>2Z! zJ<3#5ON`BC>My|MABSJ2&fB*+W2?{&xnR?Ycw!zlvq%NU9WC^Zlg}43N<3rC*j}lL zd>wUhI5X-1EU~9z966Yc7zO4Em+!%t8)2leuc6MEhy(>fvIe(S$T&Kn+df2!IqJp4 zij+HxnS2k)jR6nb9ushIT)^Igc_;aTD?}%f;9O-I!>BzW~_{ z6N-d7u}Aq~u{sP|61#H*yhlom3XWh5k1O=IIY8QAEG-<|l($S3Gs1=g+7ZT%XqJaP zh0EyjQ`Pw#6nK2RvA}0AE4T^hBCZ8%umn^yLi>C$_h+0|1a(KrQycn*~rQnJ>!}B}K=lJX5SFeiLp=&FQ0rozID|UbZ z&w~*Nc=|R`(b`(!Ln9cjnhx&rgm)0;IEZYFh3gYE5?g7t6Su;#r3;rF(8HNdVkTyV zz{Z9N5Gxyq1*zepwumU9wLHFXsLiwpo|3l;SC`>?F&a3UU|$k)8TC%wUS3|70t*Iv z1K9*_qAuxpQ-r6i9AU|b-GWYt-6RtTQwTe+2lmO%LdHfch~he`hG)d-8VWna9#-dj z1r~6yfH28|ug+&CXl95o-}t5+M{WU^F&4PFbHrqcoc6%zi7I?fIMddG=g;F|kg^JY11s}F7=aCKjI8T8BYW;4@O{Oj5Ncy5r|Eq!()YFoJhDsO$>RA0E*4Z{(Q-`0J$b3 z*Ytk?@?29w97G0i_?E1HCA%&8y+H0UX#wPUUweQ&=OybV$g?r>Th<5=0^}Z87r+dV z-ka=-vK7z`=mC&5LgfCiEkLLr z1|oqNAP!g$Yyc7fDJ7yzuKSaLtyE6#y%E|4o(k*((x{9)Q^)|007ro=K$ec9ehSC| za)EQeB_Izd0Hjoevh?1`Rg|v-_Gw>ZC_lSQ2zkxphIeOrXf}=9)OP(hYY7Nc@Gyxok zaV}ucfbZ9_o$^r?y=ef z&w1z$(Y#BMz;$AfPKHq$zJ z{*wai0(Jwbz&>Ce9s^GRLeIdffakRS0=yb{N$ac?`}Y-OuYtF~JE|x5 zsp^3S;4|)lnz+&d7QoEvh5WTL|fZ zOYaSndx81@dCo?t6SxU2cLp~F%mE9)3a|!jfSv$(4oAoqyboYU>tx+CA$!UPfe)r- zA{U|TKXQJXKaMXb0R`xz$G9aaGDDMDv0eh%?FL)}j zA4mfZ0O`O%AOkoG90SO+qvOCyAREX5asl#82HpanfCk_j@Dm`;U#qP!Yd1B6p~B)Ih1Zw$(@ zz|02(Ry8-0cs148)Ak-V2-2d!H>*U!CSxZaq&55YY5!?wF z3OEC<0C`?A93c1D$ok1q09ijro{fwJ$hv59ACM4Pt1=as29SGXvw$EV7$CF|d=WtI zBZmTEz)FCuO(knN2}OWM0nq??-Wd;U1U3WYSr)k;w*%M-><0D%slYy9KX3q$(qWX3 z0Ma!~r>HI)JO?-fTmmiw1wbKC3=p~oUP8;Il;5J9+-ofd?$Y{w%84IYi%p(KKcTXx zGCH!Zj?fG6YM=&q1-t=jfjWTPpMDS210R9Uz!%^f&eIfZRyo0!jcO zax+R9Pz5vqO+Wx>1BBXvll8S70DZs^AVk&)k!M3DKxcqF-z7wzxmf~MfHjr%rkv<) zX}J%0Us@*5Gx`Je0J$GN2p}{VTm(1)E`U2go-2^GLS#)Xc?LNe7z6kMV*x*4JTMvX z2c`lufSJH7fV>YtXg2s9U_L;eJuU)5fKY&}Q&m!> zHUs2d^j3h}drkp%0(*c|U>}eMqyrhiVSqdrB+uNkfRjKrkPDmv2%Q5b>n<(>g+LKd z3`pr3E#CkqYjkhZI(cSZ2HXYiQ5ktw@&Kp+9s-YnX8yaVci2H-RB z1^5a`sTt+(zz-Q2(fvgIH}IFrxwtQ`1dz3hJXdl9$UCNFEx7c4K5L122AOn?F?l9K)*_N;I4z%Rk@wTd znj=E~;AG9$G+-u`u^P-p)Mo?aSvGmTKuEgQaWU%T8zJOb?)tI`Q}@@rRJ$IRT$#=B z95T3fu2zQKFaOQm>=LyK`9)rp9skxAsvKc#5)h~ur{B0k5^ZdQ}eJW4Z_tzi4cwyd!(c4Ng7dFq!@l|P~p|oDK~7vwPEgf&Ts|)3^>#duRSK&T+XPcsMSwsdD<7yorTcjhY#P_@%+QW4}(&T-~i- z+q`Wi7U$yCZ}c#{zBQ7&Jf!=Mr$K|?UpnI0ddVZijOy&5eR;JFyjp0AKNBgB@ z#va@A>+O`TtK2q^>KZcZjE2QEFSU02)ZI&;2944v+*IK0@aiAue##qhzg(^EDh9)P zSagXW#pBVtcqDxQ~$WC$8wc)IUkoa&pX3kEh@bgvU{>i+X1`F2k!XtYD2?F z!x4uoGkptB=uJN}eS`Y`z~a|N&$i4LxGk?unQ$=5^wGw(Dxdxt=X7$3IyyY4_Szov z7j|!)UhXuH)g9`$=hE8I4r^9Lx;%LOu7LAuZ=clUrbire!AHOP*fnDhCMh+#Y`^^O z!id{F3|~+Flb)}ZebGy&z;9-$>fK9f9pY+TRmQrH8GiUq!y*-%&d)zb2N}JJ+B0&@ z(2t?~m*?-MIXXZ1Fs=7>-8Eldbf44Jx!676QuCHxg-UlO^QY%mPHDcey)5&>{>$$f zz0vJPT-#LODiYX-Dcw!@e)d4yUezA;=Qe!Syq#PW_-%g1%+v!1Z2s)LX7X6*K03D1 z>2Sg|?LqfS8w+iZ*SfAg<9;A!ujh%Wty_IC`tFyJ_3D7?G*zdVkt_V`r%lRgynR+@ z;q6Oj(}tFtP8soI|4W;)tIm0A<1Xy1EWXgGIy$jK`-|ePGkG@U2J;iYbiDQCOy7mK zR}}M~n=j-JY1}?6XL&!BBli{=gcgV_K@7l4?-i>2+-Hk$w_xWxHf0y3Q7Ts5J>-UUf zuB|h9dEN4y@ax_5G~ZuXISHJMfI={GMyDJZusoouQ#NcJnqBJ9&@#Qyy8nj9# z#H$Ca{SwO8NpSdGw14E7ho$@{ZO7G_tQ=GCH+;KOeBZN&Ym7p6jgG#zsrLf=5u@$Y zdd!GFGW2HAwlyN_%kBE9?=H(+AyA8Gd_V4yRaN&xBQ2Kr$Gz>i#jV>g%?qvXCQKgZ zGx=$Tx#QG=u@f5{H!b?K>>@wa-MXM%d1K)b=hXubk2L=1;_2h+Fnnw3h)>Tv`f%Dt z@5)LK7~XGZao)n9KF^*PU+Dekd~~RnP2W%T!pG67Pm+t6?^Dm0@SkgITkW24HrA%k z(zk)`sWqd{4Ny6vv&<;mF0NNe>q#cR%03$G(pL`HymNWis`0N%PQ1JI+GxK?uh#3g z?C$NBJNMj+rrG){)q?QUOTt#C;VuRUdZ3I z%-yvMy|#SxX|>Wb@o#A8Db*>j2icB~NiGTiGE%w6w=ePeJZ`3Lg z=OxDsdN9?(ZthrLZ}jC6fjj=Fk5c+|~no;uCV8pn@gaKKh*<0^r=RKL6dOtg6zva-%f|wPP zCY|^F_i*!)@`Pf&aL1i>?R!m&jJ930^McinF=Kjf@LF>4QRS+xRo_=eKNj0;9i;bA zc`-BDSXZ;QD#ayoi@~&2-y;xytlR^x5SQ==i(esgpujb3_Uk*KlI?|nt5^j_r&QB2y!K<3-38NSAU+t-(e zsBi!5B2>D6qrT~f?}xK`A#)>g!oBC6n7zgLi8*IoZPYFA$INq;LDwe!jJ@#byH-j5 zmE@R%NBwS%ww_jKuytGK!|Kh})`O3&aqZ$T?0mZ#{*6E4oOAhyYksf2xVZnZpqv}s zOZznDN0{jK=RfBReZDdwK6~t-sxvRGb}y+OHt4mHQ%EpBFtO6OM)-HxnnSrMIZRDf zb;T8zISKER>b1(cO$*sj`|6sie^k-gwhkU@rYlc{X190QFm`~xGsj`UmZXZO-5%ff z;+U(n8y`13=8AvrgM{MhBcr}O?6OEZv}{cJd!^xi&n{d2C|R&-rx!>o;rSz=06naEZmbtB}HQ(=iY_$DKhXY5=gpsX#HQufZT;=#gWsk4x z9bOx~v6y?V+F}2zgjrgT3y$Wdn5?mi*D)EMzC*CKt;5X>pC0YYx_t>*q_SD4d-vk$ z&}^msWeFXIzD~1F{1M7+_t~Vw7>@aD{U3+cjdU|zYFre;Z|^23aI<<)K4tfozMsED z?u>|;9IhF^V?*+QP+R-aHW4Ns z#UDKm-G8z6y`?a6SigpHaq*-5OI4rP_`gisbRpCH?VrH-=+)26ZdHD*=;YyEzxTV_ z%4qTBjBRx)D%<8ZrX60eEPB|7o{qIobQ@jvjXoK$!?VMUx?L|ap4m6mw?5y!Yd;T_ zn;t8BpL_Ibxv9qS196MZb7uU!H~8-Q?bZX&eX`zIt+iV)OLO;8`yN(5!aaktqTZKg z+EqB_thY^R-dVUt@7VaNl-AdJN866r_1NU+%ChRmuV+|vn|m(5Va<$>Mc3LDcFZ*w zV3wEBkX_*!-PV-O*4=JoVVR1)&AL_c$@ySe zg3!6b#WByV?a8r~9!?(@{+L`QG+Jk^7jil9Uf@-?UVUH9^AEhaX?w;&Tg^Jb^xa!7 ze!KeCCi$^>(9$b?`hMfPsT$;_bToPOc=fcUA2+$_Tz_}(ljc>|@m4GL2Ip;>r&Uty zvNiFn%C^o!y0x+LvprnX_%O4bN*~pe^E#fge!1w7b)qefU#eY|`=xI9H~PTk$c^32 zx=groTG!bq$ERygZC+(Pr`7xP72`Ugov;0K?`|Afzqih`W<#4o-~;EpHdgeu z`r-CSv$@BEWg9N;y!@p3nrP0WP*bjRzvgG3CRe4nzNlUiD4yFl@cik}iLM=AtTg)A zaogqTVpHAo(HFcK+6vXMdh)gKeoUjo;v&v5h6Uyhz`}iPU zqf5r1;OoO&Hm7R!dz#s9TeC@+0c?J&AJ$I$*#2v~qOjtXXZoc5UZxXOzkBY~or{wL zrn($j^W4qK)9ZcddiVS9gU$qtv*)M1De+JIuxJYMHaqgD`pmoUODaRg{WTc2vFOUe zL~Zi|yPahPWf|Ujf-{4)wl#0rW8b=Y(YBe6qSURg0xjQXHYQ~K9oA&`-wd zW&hEuvF?jf2Q)e5I>wFtx}ws4?AhYHlH27+@=k}kpRix|DdE-08HVSly{-Ou;#*>c z-kT$z%HOv3Fk1LHA-u|VS$K_F&xqw8?~WK1X4F~dhvA8&5lJ(*j=ZOB^-z4EV{VuI zqM)jpO^?3-({Jr|k{y<#y)vu?7LUgWS{%UALP^FnvKw|!)#e`M{`$EBX1 zwN?!ZuKKa;Ov!$)$|u}s`hs^lp%0#o7}edQ<5HJ^m&)hn%-?%!)fUPguMLh_7D z)po6Y^=7Hbl+w(G+$Vt*PDA<{Wi9fW*nQ8qpC?W0))bY^`|Z%lv4VeUQS`IwKKBl} zC%S%lH05DHQCZA_zx4-~^Q$s;7xes|{h>`--KlwlnhtgAKBuz(?v2-rW_{?JwKBGN zb2zqe*|d|;SoTe+I}iMbd7jnRn6sa;pa=W+7XsN?L0zuow)=Xb0s_1yJL?ZpJ8ZhaDZd32m~uFxZgE!;d`9`O%FUGd`yClTZ?)5yoy>0A%M!fz$d%f|sl|K%3s}=>-q@BH-!Eg9+ z;Zu)kmrQNby7|hW+V$^}z2>hraJuIWUSQ#%|DDRGV6#c8zd`;3*R#gt zA;&XrL)Gp}jdn*8lPV+9d%0Wn`aHzAV%EXFYI~hNCMbVybEeORTi$%-R@FsL5GY7_GOx&EhypxfUVNcH)`}U9aHc`!*dN?Dj_|v}O z9WVWBh<_D+W?kr9BkR)g=ac`K4jg%9Z?B4T0eeFoj(u!xr`#%e|L=IuT_3IS-Z8ntC`uZs-VhxfqwT6>s!ybHpX7V&#Iwn?7O5FJ+|Gk+;rog z=6H|(iwxWoS1lU3$NQ2=TXFa6)8F@O^}(UKs@w1h%|F&Hf6zDYyx3B-PWahiz|9TZ zt)X`R_FvPU{M@@HCHkUH(Z=wn!y=c?%`|i#kyH?tyS%8jP*56t*KT{$DLtEKy&pZ% z`c&P2(}&hx1$P6AE|=RK%e5QW+CoXC=|J}Qz~<3WwJyJh^F?isS-o&vu^=$SCRzFO zlTI=3N4VSBC3+0IWB0kZP4fPKrk%{|ALwR{S@5ji=(Q_ny8i5LK5o8);o#p3#srUz z)!UjhyxFJK`6ZkotzzaZN{KgAK3LCws4Rn%VRI@caI@ zJ|@qXcly3}g>6j`sT@W>>lk?u&+UawSZ3$fSE?}9uVVhTXriYb& z`59AG81rOF$bjl(UCR&OYYltu`4{S^(c9>pPwR>!4Xu~=JUG1LfgKv%KTg#jI;84P zo>I4n>0zp^lC{>iFL3|oWUVFASASSKU|8P~`>tpO7>@9E_&zP$$UV_9`hM7($L%=F z2k0Lew{qaRzjIKKG5yQbKfCRXxSMVFx2RLR z%d52Om&~zo4(!i8g|EImDggY9;3RwuFbyalcc%)#JJ$G1`8VE zhip-8JdrcP`^t9Hy$Ak&(x@htbw`U#^-QViYZCmZ+% zl??A+^k&HH6V@heqhq`?`pk>k9CT}B?Qnx0b-s(b)UbYJv)irq4D3eT^0=v!Uzj~(hcwG4Y zywNY~PknENAFrF@O`rD0}XDkE)&|NSsFtc%eMnfBfQx zcxKjw-gQsraBI`&W}i5Fs;T;=8<)4+bZ^idzY!Z%?=HS}yl-yWA?G-cBORkx4g8%f z_Ffa<8DG48FL&?fVdzUoKb_pHTf_S=%iq{ze2(SQM>XA^RamcF^V!Cv?FWYp>&t#O z{a;>r=B&Kmf27BfzQOTEJ?btEX!}TG=Xc}R!5VG1-Q5wN5^HcfGOcEOMA+C3@y2^k zuH3A*X42}A0gE&9CwwKNE}&Y$BI@i*=4eKSs?ujgZLwM#S?^*dYBe`NU`ja%b~ zi`{0%_15V1{ett4%5S6BNA6#9hp+s3mG{5kC6?*=6Ze@JcI6$|#M#@7?!4?f&!Ct7mVlPw37$repK5e>UtmduJR82-BFC z=ImaPUMpTAnEB+&H`l8HNw{OHkCHr~4tFNhLC#MG3 z%~>7#dv0N;LAN#UF5Xn%J;!6%Jk`^|Ke>$yATb>M1>3 zlKk2~wKSg?HTUMh=HdZ!=B&B&;M&R{UmL?AKL@}68Gox?!SR|82RHQA2>E@%+5W}1 z(K|iGZc#o5i;nK8&H1p&rq{vJS7$Ez{tN!GV2S16tk&c58$1`gZaV*WPr8}m5ncO@ zpKct~jOl#fhxfy2*7iQx`URDJi*G!)`r-)NmvcwzJvb388h6dL=iz?p$=@wHROHlU z_Sxe(%gi9)c3(Z`b(dz0A2NHD;fdp10RqxI>I_!vlJiTo57sENn=8Vni=VSY^ zf9JR}e}=Ej?+~r=bAo!TNAQVruV;DBdGcuB*`gn}f@=-;7>?J{Dm&iP_%^uVhwtZA z%@-S znFq!$Dblr@IMJs;=-HvL;jzI8wf+TT47MGQA80?e@W-cX&7OaJl4cyAt};0=SwH&u zr>EUT>h+o{3PLX{o#+rCFq}T>fsL2_o|jLjRlQVmE8jNiy~Ya5@;rW#;FPgv%tkkr z&OuX|ty)dI{N%HfT4kH*WsSEnd|9{5tE$X2_}OT&n~vSmWb-T2C#cNjN7#idvFv@= zVgF)&@|+J3=N;)#;ZW4Oy3VA0Lixr~zhm#*w@J41ZL1$Y0R7l;)3s;!19k@d=K;Ze zoWoCe*KTy_s?z6DYWp?=!aTQ?G<~RhmxR6@vY0$+L+&AK!=8Wt4u03;pz`%S7a#AA zG98?5T-drS@bI)ns%QJU?1&%q*6jH+JWKg{>GiC(zrMO$Ua>yL?%lN6t^V}VXutJt zyY2-VqI0(b!wXi`zD{tT6!b^O%&_X5aoq3IpBB829NkCPOY#ynZzp%a3EAV0?1*~F3Pg_&@aRMCV$GL-bqw@0E(M7&|JQnWCv(FhIU!JL8o){^R zrz;p|2h3-A{r#$7K5tjBA8{0n=QX^1A+KLO70j#M3i4dtTmCrc`O1%PsbKzhR?zOT zWchLaV9~g|{O=pdx5vtSx%;W5f_76BY+tgbTwc3(@WP%vd9;~)d7^^-j&ohUy$B29 z<;B0=S-yOTf_~L5lplY!xqSH^1>1MFg85*KMf~#e-0@g`{GAH67g>KPFHTrz`SSS+ z#&a~{%iE946&yFnI$C-5{}dd@vMl81}wUopP-<>Llv|; zLqWUM2J+k0#mmI<_ODS2#y@Yf{5Yc&T+jSaFweWMlt0dGF3ZoyMZx^PtDxNx{pIKB zs$hIxDadp3dHHcRDVSHi734WgLHy?m?1v~gE}c|x{TXd7KhH7+`}K*%^2dJy=CV-E zd>*f$zXw$1$0<>8T{K<6d2=1^vCDV7sqVkbkIx>+M+zu7{lz^!K%b{UseA4VE__b}Pu=PeB|%1^v3H zVBFqk$!}Lh!Tw^d;P=Q*1;?d41#(6~oH_;h*A~dn^MIxN{i|6)9I`fA-Z*ctkT0L2 zVE?Md$C2d432q}_J`L^4J1%AD%C}FzJKXZ(uTe0srdrCkpRK@tnS$edd8+(4DhlTL z2?g`2_LlrO}YqN8UJhRd766uV8)#Ac(v?a}><0INU6f zXMab*@r1m`CNIxq1=|a^4dlkp#Bp0*yYCjsmw!}{kHIDR`Lsv7LZBs?be5k_se&djkNo-2OF{f^3ij(F1?PpMzvZ{PRKfm|qF_5J1!f8lCQ*&5*Px4YFNNV4G8f&jz&Pp&{C6t2SYa~wSJxn~1bRSW|#|(%(pN}8H zARozJyq7hDwO_5u#+SxX!N((rz4``LF1=^I{|+l(x15zr`!$=!*-qmi4GA^Jv-W?j zSbOq04?+okY(5p_#Uc5ZxeKyYDJl0-1m+UvP z_I~|Yc}E&2!hp3GT>fwSZj$R6b;d@!mBjL{E$cwug(CU;l9!D^W~`WLyPSOn@obFVq>Y)BoLW0o^WtTWpti z_t-qS^rhW?Y#3%Z&GR?S6JaH!-<56mH+dNoq$Bx@@8w=#;{?uT^O5$K{9{Zq4(BV_ ze1=l{0seFx=u2l^seCrhgT%f|Yj%9jQF$7!uZa9Ed0`tQjk6y6De3Pz@=_>~7-J+Q8q3a1gq2Vg-A^U|xC{~xDtEz$Oh~(ybbd{` z?+u!>a^(+f9I5?6A2!by%4J<=XT( zCjFj@rv=?!GuQ#{M^1F0t!At|i@c-@>LmG#_xHE3al(4C@ul)klItIJW+Z)K5{Dg@ z@PQe!9TRlfOuX3cF?%rq$o5Jd!)`BKYOd3rwO`PkwZ}A;kcEhCcN>RowYe4hMEJ4!g)pj3DWFW@Fw;=7|^EuJkx|5+6+@_NC-ye2|&sFU}*zY@8(W z0yk(Il{*Mo`}uWjhw`ZW9~vTYzC2~+z3Kk@5yuZA7c{YQQ)=H7&dPnsOa7oqRGvDI zmG?De<$b8!+L_HKfxIXRlJ;xOO4dHfgteE>lZ(q(`5y8?0g&|g+-n#c$0Lu8Bc12k zXo%$5m*y#wc;UU;!K_^TkIjDom8au(8L>~GFSX-vAtC=?to>l}f(LI4%+U6I)ohKO2sjg#Deg>q=h!2T9|P?ZCJ#H(RvB!UgT%dx+)BSYO zSk}HwkG02PNLR-z+4%nV{+rpF?H6wcYwsZO!n@+Cto-+WRxX`~s=;jhjqO-Dx+$R#_`ONS zt>yJkUwU3^r2kYvI?uIm03`M;uUoWdvvPg9UrUekQ|GhsTV8KG_Gj%yo!ESS(|j(C zVdWF)IQOFRlyp|UjC^9zh7*g(s}Dj z&ldy8%lRPk{U<_!quKHCrRPEEaeDpViK6zc4Hk3Up%SRa{mcOXW8Pu=1AY{p}Cg{X#f_&Crh8cjmM0y3qXs z(@8?c_H3Mk-`R1%?ku6?QLMe+RW?uQJYOxjU#HF-q%YlHr}m}v_e)hinGrxvuS4FoxDI)KmyJ`?;y4hh#*Y7sQS1mv=NnhZ z+E1eAYfM)O-ScGI-9bO9ARXs)T$qt@^X$fsXHROcCixw$&bW||k$|MvGikA`eIdOb zlkTU7a3UaaEa-JhR~n~NDk~r3#K!ld@`oC%eEVH?K1l6@+p=;Gdc7?j|4X=FAn~8l z-(S*p7c61ryJ-GW`C1{{-;wlsMtWWwOn)z1TxavaWtD`^g|l&5UKjBUS$V)4Hcy=9 zBvfF)9)HA}SvfX`gsSQJrG|cZC6rE-`5tVXVDix=kelQ$#^nALO zeAEdvlge{~*nYjJW9KIhgAz*o%f^|Rz{bJP6A5*j#M%$0`bH`7wDt2pev)(#W#xD2`TCd! zJFiUXac?F4of1HQr*x)qe$(rjtQOZZiFE$VZ!v$`;6O*_$>Im>xLMISU42;j$PR3t z(s4^&z>beH`49*Qn_EKtXR~r!@&OT$bR3Lkvhv{jtXz6th@8d7KSj?M((~_G1=lBL z!L0o;3pSqsNh|nfNe(N|8qUhuRv0GVoRzPoznj9Sy=HIrx>2y59nT=vjY*Q+H~XLK zBuBZhaTf7dL+O6^`421iq4P(2e7H=1*H@8`tblB3yBSD;jPn!n@h(tzDql#iyDrfW z-rS(`&;bV)V*l<7yIrK?liQn>XEn0&J~Yn91+3hiUM~%$^4m6Sf1{SM{q0ZZPbVXG zy9lnZ`E;T7^RS1b)Q66a9D_(vXlfhLOlyUN70dVda|iI_E$8(L`3hnjZJ0*Ii$xuyR9s z{U+UBZr53P%j>AkUhMd^JPtHtpvdozme)~sbUq(YW5-iE|4-dw0F4v5 zkd?Q$X5&lGr|vk=k@4R}Kl&%#UZX2n`HrQm{csxRUN$RVIf<1QP4Ct&-9%Pk4LKESqHM6Y{$QF{k^y`e+%m&W-s zj6F}$A*989h=^|(K%isH{z*jC1_yxc}fmmmLI#7?$ zemw_2@)rCEHD{jq-vxidsX_-~T_}xs>}JGcs#hl-D*CW7;u*D9XS55QuI+>lEf38T z!Fugw)CHyk-nO04x#|XQyITarCv#60`j;SYspB~Aae<$Xd@oH~^V~oVh4ta+ZA2dw ze=hXrIIKt1KmOx%q4VQ<;YZ_#MG=|r58-ma|AJk;>NdeY3Gs}|?bNKmZ$q9z=hs&- zFK$8}Psg$6Gr@n)s;4~qionNWeWZHQe6zr>5~&@P8uk z>rg*h2t85x?{bsa!#cz>I|KhXBFK8aGxBme?w_Gu+rQ^77W{RSyzL%H_L=qMg5L<7 zhSfX^{!8$m8Y^(6e;n-gVqAQu`urf-ALb|YwkXIX_=V?UqUW|BKM(S(J4onj{4ldY z`02e@^!6O+TN6!WroRvTU>~`8d?_qF-#7nDcN8MOvGA{(8i>mOHS2dBX7m{{iS+bh_yInpxuauLt}A_@lLa znIb)^|9zVapD$Z+dw8WJFC6g z5_R*l?i9Hx|C8w-%;(NqiX1x7-!a_+UyC}v+R2%Fi~l>$FG1%ArwIIhOaCvtUEpiFgwL~p{}KH1w1iCPg8={IX@dXhUfzCPfqdqoO=MoE z-hP6(*N&s!IbZ11)d`)uK|dE3_}y5)?*RDM5l8KUII0EkKdch`lMfX-djP)dNrA6e zE^wXir=efxS^3Xfdu0C3;0s;pnFuZCS9xrs#SZC?Df9-XFPxzM5QNR3EDpc|Ko{c<-#w~lEBlx!>{wFb- zCxZI#l&=c^zXyD?Ho<=jdam++@(6)Hu)Va~0Q|8upzN1V|B1kV2KfD}1^?}%1TL*m zop-Ik?Re>GTF)~7*KaI(rE>V@p@Kgh_0WSre^o#{lSaSZu9Fs@1OAOi3H`IMe}l}F zc|P1s=x6yddwQrl<~bSuebldopXWyj{G(F^|2pWo#&4(GBYvUXs?+`PJ;6^{{`WTc z_e&NF{ZG;EkG?DT^R4*vN#r3HU_GUNGqkni0e_zyvz>-QFUj+WO#<9{Ljy%O~o^><4@68c*peo*~yj|=?f%|stm z{>Ob!;A!|fja#n#vA}1|6MPyb^Srm8#1#+lMd$Ql^`mv906ZUWM;x03on7I7*I~Xa0zBL*_!oU%=xdyCdq&{9Baff!lFN3*@{Aaway+Gbtbr*=`fq6V&~eN;9F|Nx`^Zb{x|5g1}E76vQ1c zE;k{LoxvBj)5G5p;b)DR@1sLwb`d$N9k>Sa$s#^cf3(A;Lf?*OULO?rpHV+LK*)zy z(Eu@@qmZB1aer$cfluO(XwXAyV4exzl=|;me0erKDxZJD?p+GIN3WabCNdzb&vyK< z7d6D~+Hu12Qv`0u2?rk{@Mlq9R(=Mt@8aUKMV{)9en%6N>A&~7@UQ*)>=uFF{&m5h z13vFZUSe~r-gIe1@J|4pF5r{88Twa0BJ`=7=D7&<9ebbT?g8<`#}j3~@57hO)3Xlx za0B9m$E`TwUx@P)*9iYJ&0BQ0_+-&TJ5JcCSKtd^XVhM8v4-s`=@shfI$u5q`@BEw z^VdQDpL8ya_t~y^Pezu{{qnQhu_A{S!!T`e}E8}&r@L!mH!Ve5cpe&Z&l9Uf!%I^-5vuv zPi!anS>zj)|GtAoKhxh6KJNnli^qxF-r^4u(4+eEGUA7<6+he<6Z-e>DRNLg|Jo?@ zZ(Jt=ST5v3_beCu58-F;M!T;+FK~N5RWtO~jw_a6-^G>IzKaD|cifD1hw`%y`wSmN zoUC?oqhqAqpX?(1tNfER9oW8I%O3`zhrgx8&#B7<-;NVnu+F*-@zTeF9@-|r{~k*N z!Q=a}RhPdO{q4m%OUL(q)Ro>ziXeA`zI|}1(76=rT!=Z;Pk{&19|OCp^Y=39AopwK zP10ZG^Qip=-}cvULe7gJXPtL;p6~6-UvUw7=E18-aIc} zC;YrHSNJ?0@R`(a?$@_bm#hOkjd?Wv?_R%f_U{FM({Bo$mB9bVoKvIy!w(7kF~DaB z_}^m|3Y}drPt{({*-G{^FS6=5AHwgyKU3szx-=8I2=;K5wN4q;C-k?(xO-^$8Hh$`&i%cx5N0ElN0zCVTYA|9mU(s|JJ?2&z^!F z`tDr8zZ3ZuQg8Ddi}>yS?~35bY?|k&ZlPoQ%|_}k&x_HY2tI#jkDo8W@6SdZME%Pi zOQl`gKep^G^zT7_L+9^7-x2()F;8_|#vtx`6>--nX*SeJ|KR>!${$Lj=X}6_8sL9V z#Cjq9xbVL>@CPs-um6XP`-_0@u%pC#hw%qn=+Sk}y#fArO|!^n{&b=9bI|z~;(zNlH+Aj@aXJQ+d94uj7VaPC9b zH5U^;^S|Z~qR%v}<~f8WxH(^7?E^ezt>7GE ze^KD;uJx&4s?5Q$d$K4_Asy=KrTi`GL+6(_H_EYu!O!Vym z@Of*1Up^Z64V&Ui0SB3Kf zKn6s_$f2j;}=nr?xJQ{=i;ns?eIQ+|#1pf)>!zc7R z)1QbqYER&we7wl#9@NV&1pJtt1iu^hS=Zyc|3TpP{+vUx&K-?)?mW=BIxhIHTYB=^ z&H^8W_32lD|JNr4zViv9SDOR=FT}~WAx>7g-9rm8_T!iTRPYy3Jjc)GR|%bs4)W3& z^Amv|c!a>!Uth6K;O&@?s^_PjD)8HI4oL0W-rGwYxcV5ehbsU60KfeA3Bu=DTMOl1 zV_a^+xq~aMa|dm-L5s(0+I_+&4YzsPZxnvchaFQpGZS&+E1#){75oFRF23Aa7k}0& zbb7JQRXP6<<8J%qQP?lh%OBsPr$fkx-be|b?U-L`4;Or0;IHF+rP9BO{=xma1nXil zkLLN()dJrgajE*X`(6ZmsmS5Gz(1SpF#C})@FUvm^I?B%zyI%tgid~m&{+XGH-1sz zGhvq^fJb0IH{y@$(enV{H^9H&I#VX%da@V%tRjZFU!$St%1={5;0K~Uva6tnzWW?~ zcaZWhb=Yq_3h+Cyf94A~C#B>2P)_t`+&jV#nLG2W>J&MjWbL#1>@I0{)g0;Xc+h`s zmcZ>eA&z}S4fhLv5Ad%hL(Tnq75k`_&TbSyGW_~o1z+nslc`-EmlZfasPp1u>_f=o zd}|u?S0mp381eQ@g~PsWZP~ZCc9V8@L>)W{d~Rpk&=*6m>?rXqz@Zhij$r%H@|=v< zKOoSdi-gV^>^oBXmLUb^e%W!$?;a7j9iJ?KKEH^(qOKPnfc@DTd3)9K|5+?_?6_s_ zo-&RTJ`j1%M+ahu3;bEsovAtVoN>6&x$_?qU+oL{HFE|39n3qmlQ+;pn)_wPIeeg- z;g2A1p#JL(vR5Wg2zw%2(KjBq7CMh!FA!1#^Nhbu=p1^Sz}2o^0y{7Paj(+f2lm`P zFL39#h0fYWp_2#wJux562QLY>5%m9;i0f9t9%{S$FBLwwhrUHY=Q-FJd%w^hUzc|G zK%ArVZY|dJ%jU_v({=qC%nN&8+%vyo{U05A1^WQio~+0G9rZV%vmX4sMvBYwpM>>= z#-;mF#~J=*D?gduPx3jt;{5yeptA)2Hx2(g7Vzzs3!Up=mnhsa&%;>9ZH~MvsgrqL zJ5c7!ruz$@TEDyMpF-!rb7Wjj0sal-?^sVl>&4=&m!Cs}agqPutbFfJ?-Ti~*?yn%k{e7uU*O>AcdkUv=}-3#pme`?237ym%` z?1G-FzTG@YCIb?Mp8{4agK7yYv1 zv<1fqou?2FJLCIh;eRgjt~5;MIbbgEvHn%NG4PteS7YKf0RN1q#ZRq4{5Avd9l-zZ zJ`%gC?cV#8&G<)jlV_FYv<}1U?@4*N}r?J^ye= zfsdnd_t1WA_pZRlV_%Bu z=cX$Jek^8>&m@LxO*9O6XAe!#v-P$$YWT zf4$Qv_;wt1N4MZV0{fg0`#rvH--K}oDb5t{Q=0q zK37|Jk>K0$*qzvyeg@)0)z5XX+lOKQq|Vl|t zeWbwGTkEx59~S!W>-q)by9#!49rT&h+dM-g5a#oBoX1hW-@K>Lx8uywVZmRE{c#*YiULJ$_j1Ht>eqf3 zP$&BBR)U|$eK@m0=Udka{Hf_eU&npI9%45pT`Uu&hyLbgAH-cBH&P>Qi0oX-EIN(ssEWO_;#GuK=BOo zbI^duhuoie)}fC4ai`3q1jg$Snt+Tyf1Us|uD&=e@EcLbQGJ_+aa@LbR49FFo^ja! z@X7N+|4!JY_5UOJjeV^A#>MbE_W6;MHWhiUM4jSD(ElYF5ax5iM#5(U;5Skomf`JK zhw8k(`eniYD&iK6yEcAR;Jt_gsXONRD;Wx=^OO}gK9dyq1nfT<3;Y!3eoSTXFzUhCkMVMbdJNiQtf|Yyuj`AEHmB_ z`1^>5bsk+dUEub4+mFdlvHv~#Muv*}| zXx$m`_0$ojpT#*c>W+D~q4gKTw@15mfFE+V(6QsprL^yh+dcIb;d58$|4fYI8T$!8 zKLDLEM+p9{);^XeuNQlGnB~9jLEM$UR`iFar+Gdlg52&B*d=K_6xt*!@Z-NM?d}i! z9bpfTfIZZC{mfdypKyZU>o{I>nZS=lT%_amDXpVv(Txp<~x6CR``*U%>D01Ui>t{qhj<#x#A* z!)}r3ujvpz<$pt=Ut^!fj>pRg9s~S8&lUO~VV?t)>CLkk{^CUB0o4BdeTnpI?HfX8 zH0Zo`gV5REsu#>6v9SK^@|ehH4DeTcQQ%Ea3A`EbB-Sa@u}--S@RMMFu7~|mdz(PL ztONBjgg>E8C?Cu1zKMFr_Mmg(mI8m|IvL;TfR83Y@qE1g9^vP*E#!x@o)LM5uztTD z_{Ve!ou^TEQ+-=}mf&AGQzWnWeTZ`gAb%W_2rc=!$YBBUnYv%)g=2(%9q6k+S{4xJ zjQyd|xg6(8v|exu^km`NGG4y{|Ksi#d^-;L$4LTTVy(MBg`MB^XF_Ko=-fLf`n(3~ zMCo-Xl!86^@Cvaf^rv|)g&*G?`xs-Ovp?{+I8o@+HU{(j>H*lQ=sDK) z8ix-q5d0RL%TWE?=LC`G#yEGmHQJrBo8a5=#+NZ)UckO4wO5B7A^3LO@+ADo_*KIH zKS4iC@@GBlK>kzhLwvfxM%90B z_1STJfSsP)M&>`EvypdQx2N#Asi=GC8(0UuvAY+3EA;Rr=%LE9@lu>9@wFSpTKO#cO}_jUfR#X2j3cxE%u{}a~lH)8#+>y()@h0b{&$VAck`}+If z--m2J1`dc@NED; z1NvacA)i6cXCdFKa!x)j^mjp?S?$mBR|ARvyqgd7UvzlZ&hGk||S;+f~36h2p?!`E#i@xY3sB@$3Sd*w^; z*SMegPSDv7e(fOmHPwf|ER=rP@zrH#z^+>Bm-l;w&!=IR)Q(ZOYWTkc`;nBN<;w;B zH{=!7PaOe0-yU&-`jO>;uLk@h@IRCMJKG;SzM2C4vG)g#0{)NI$%s?{$YTZwtZK`M60yTzCF^ zfP&%;-dEtwXm=~2LdrjMtUcdM7$j==|3|#jef=o%NJgWO=qj zK1TxnF3I22agO!sRo4vBlks`LEGH zF#PCW2%j3Ce1tsV6UY;82fO#=K_bub*1Z!e7t6Se!9H7Zi{|;>InwT@SdVWHcq2Iu zmj5E$|3+rSJd^u{pCO!s(>VO*Uok$#QP`iLe(ioHh+~#wP`C$5&q;CvncgyJWs>ypgg1;S>^By@*a0SCURE45S}mNdnfi$i1nj;!D)fO`g0Q2edmFnkNzO= z-K~9$KRR6CuOgl#v76`Hs|Efd@|J36e*BQYKV2;RD4%a1EAS6@6}Z~NlcU1tj=vXq zs-A3vIHwu&NaxGAe+iwIZwnoTKaF+Pw6!vhi=ek}!~Tr1?9Vl1h*%DGJhR6Z!p}Qb zd->dTYr(hcYX`3pd$kDl)BPZy?ROOXW3BqvF0?O&_3#YbA2JPm-T{679nLB23py_# zzIp+9DwY3(h?DyeCu`ie7tLSp*KOE$F+=%59D6h3SjB%cDgE6N^>noZzn&<3&b>&+ zCdKx2E#AENZM7uv#?X}?YQEya|J$#brzXN^BjzI z^m7=mIe@=N27&2!!;drq9=T8SwjKN2wgdbNpA&w@f*&2s0rC&Kx@L$?l=uZdz0}mDWI^^qg zzT7cJ;1jSfg{G}}&c(bq5%WUh&m|O(aeVSO>)wymhY6k6!Kd1*x1JIBx!)9iwA~*f zuX{JbDfRl#3`eG4kjzaq}RA9-wz$8OnJ&o_ZNIS{;5N|&*J>i4!|G0RqzkOdRF;7lO`tXj~y57mk>V3VSPFdbXx8ey;_Mp z7}O+m#w$YS%u|K`w}AiJ3j(+Aso3cTf!~dI>3HCO3-MA2@zONFw{(O!0 zRWklY$p7yGKI_5H1D^^%At=fh5O3VMvGhyr^CL8Wc^t2_{CMUVq5l-lTdAG-c|`cM z@6&kjEP=n&B=ohv%c*_l)Be8FlgNj>@~K!VOuNv|rwG0skDUU&dT~?f*AjHEi54tO ze-iSC;~|HuN&OgpAo40S-OST|l=N%U-wJ`#F<$4~B={eqUZ!?zXlH@Hit|u=fzGmT z3p|TUSRM z75v3KG3inKoyl*q9xi%M;G{O@*=~1f*WNd~D=k16|BkN-KNkZ3Z@&}z?TEKm3YpM3 z9}4`HvxUCu|I3>Qefz%a2}cY3fhUE&>g_|{6gmU&*9!moj|AR*T`|OK8!rd5m&*#?}+^p-$%QzljCE3sQZafjzAwyhTg75{iq4} zT?yf5=H?=2U4J!PDDct91E}5j7vgGrpZ~KYV&?xWhJ4)AaNN$BKH^YZ!DV*l5b9o55qt`Is`A^)S} zzWQ*%e+BhQwYNvmx{UeXeJknj5cs*0+F|&;sK1ceH_tPl7dm#F{3Phu`$85 z@5gvidoB|E%_j+c zmCtG#Xr}+jTjG$Dki#~JGhfAh{$m0E-`50xBWz6A5AaU|;XAAsw#Jy@aX2PELLLX?GrFpL3U*z`efY2xPHc#?Zp>sX# zq|!MN>ycBj9_a!8<;MyBaj4f^0Qk|!dwguIUk-x5e&ASX_j@9y(75M?&J8CC;13w`^$t4}Tw`mbB(mrtb$%kA3!cg1%F zzCFfK?Z#2COZIn{u6aZ7cY(j&4E>5j|3AD>^qNtp zkuHIMjJ%4*QSbhjz-|8<-&y*5&wq=Ye*^m8ga6tE>x*vz{=_uFAF|dLgI^H1eNXjm z0si-{0RKK4`Q!(V6FGdQa-ct1{ySUWcbM|2z#lqa_}BjK0zZ4(EP-nszY}?tm)DE_ zJc52bJz4mF!Sb`4&J%d(LBUu0U$|V_?S=og0SN=)-rqbDOiok6@{<--ApO15hdGPrhG0b$9K@K{9djkA^ z??RDt0{g7A-3%@0n2vqlRN}V+-!3csPeQv-BHkNi#d|$CueAAUkpqPX=6Q*hjZA-I z+y|xc`H>h$dtc~_2MN9%S1dJ+LE%Z`)&+WTY2J|OtF&6R#B z{+~_|_^3L8Yh2g!MWOT7j|Kh>^lLj>$Z)@=qrR+u@EP!PJ>neYa|SIm7=L%{&sY50 zHWK)`u#>dRF;DtPY1jTxgVH7Yhefv8guV8(>8O|O59QZw32%q+MSFgqXI{UksqvJx~-bZ)rUj+UZ{L8OE z|I-11+ws6>ozm`kR^96OyCi--&$_qa2KezY*f*u?zCXfWJOF>8>&h)aXTYL!&HKWS z9ar4=guo+%GA=s5Rzw7TAnsM5u*W?AhFzL|jp*|z*o~>EhuYt5|HDy2=TqbX#)8g@ zpGbcXv+{>SSnpqnd(w^t{w0rr&!m^nw-C?VyPO;rJu5{mLVLd?_&1~8r{nU^E|I@| zzVf$=1#ZV7{~(2Dy}As0NV^k07W^$Bhf8RHnExNHl6KWEJOO+DDB^sD z??CS{z8(J@zOT@USoZ-wjQL`JAFBT*q4PTOc&eYR0r3oXhyAjBzxpqUZRW?0L!PP^ zKfds08FyUA5PIuQk)$t#=NtvO-9`9J-;P^OqWlB%^KwY&H$nd2e^l^K zPm4TLptBqFXEEYfGRx*U9DXp5eJqCpek$2LleeEM7W)#w_o4uX`MG~U=o5S9dFO8e z-xT!)wf`$y1U?`3TVQ0`Mbay(cjIKe!IZ!c;+zV z-)65D`o94Fx6T)Q`@54DQee+~+VRX&G{JdXLRKE*>Fp&C`3mZZ+TR4`ogL>adQs?H ziT!>@gP%LlUpxMp)gf|w0OyiE2L3s#gwGj>57lq}Dkk`LTy)D`f`8&)#Q=zQg+j@D znV-?2^Q`^bhax_|?w?}MX}M>fj)1u6FV717J5e9hb?8;_vqw!6I-h{fo}UQ5yj|9H+O3??^=W&SNUPgXw zSKx08IgI~M_+J73x1JvF{hX z8F``SwxEEMo-d=_2acEV{U`D{ar0{^^kkjT$)es$!)>0E$ieaWuE4%BQg8FjoFn*m zB7Rf<-UT~vpFhg(DfpWsKSpX}o<_9$A^e5fz4P`IJGuMGA{msoL+4BuIxA3j({{g& z{=UDZ^q0ag^SsqB{k6ZVdph>%?Rd4&CwFh2?IsKUmRLW|6maNQw2olAoqkU6soZIv zZJ<}vP)~I1(lJ732zf2#GfV98cs;FkE6`asSMcAzL+C61h4Td8&iDQ`FZ|5@K=5Ax zpSyom;9K;dUldRClR{o-GV($i|2+K-X?HdD1K%y^p=+bk?t#0D9;zQd6#I_s^Cn+_ z-TN}uai@dM6*~%@^{97D13VEB2VN79pPwBQI+OMge$GI@e)OQgU+EFJ%5CM90>62x zz|}9zgFYVyecm7Z4DBZP7hCs_?Yoi4r@^WpJ@sXYE538S*uzaQj*Fm&FXFs_+S|PX z;>^d>((YX7kNVT`u#z(S0A|I0>(?S2yV+Edt-l|=?o5q3hU&Q)Oyg(>)1?j{-mX6zSLZz~}qOul@!3Qk_R@TZMl+ z{`vfRp<~BCA=nc;{(0jj!GHR2X?F3e)0Oy6b2K^&05c(fk>!Ss*Z}#^fdJhwP`+K|hApSfE`;=6#c7ZrAX` z_QN^2>w*6rT41t1Z;bt=q&DU`|8;@e@!03Fei{FfjH7-}`Ci2Bi!t9-|NoH^I(A(2 z@UI1K$2sTDM!QyAapm&@KOOg#y#PM5m`4Nfo2M!Njp7IYfqjo!&uX41a67KJ;BL{M zkaaKRJm|9>Z)`MG_<0<4MxEF9^~$)9`5zg_?ZMAuS;2p0g2+wnv!n0iVaM6h5b6Uz5fO8($*u-b19p-vIx_ZwP$j-2|?A z-8*Rk#r)gx!;f19zU#(co=G|D#JGBpAxKHfQ7}y^QgUvIZ0(rX(>mWDfXEF^mxBDsNta|v~ ze1UJivqfw%FeA@cbd@c)eUnw|H4WunmOK;4Ii$vnrQj=9e{(qBsNo98I_!6op6)E)C&Lk%(i zD^aJ`aXb_L=rZ`D7U2K&Lcu=)`{;DOM9&sI3|Z%Gr_6yItT-pRr@&WyAoAG?<1+O! zp}*}Efvf*I<0*mLamCJKgw8JS3%-uyDv}%btNV{KUOJ9fV_ZgKTw>_gEATt#S^En1 z!TMstJwksa_`LO2p+6h;Q0ec8{O~gDe^dA$QGfgs+T9H8er=iXUx)L;2Lb*IiXWK& z^ZqIA{sQoYCrG=izbbH2Z}VJofauS;5z!x&+as`77a^Xx5A$yK(}a%w9oSCzmrMIZ ze^j1#z@OUw`e%be=XT_=)xRA4bLa!=4yr%by&(AZ_hgg%3jZgplXf*um`DO)IecQ( zH^WZ|d>-oBuVGw1BY`mf&vCw(*f!4`*bV!8Qqw7}X8e6ti`*7szI>kancPyOR{=Y=y z%VJC*)|Wbg5N8fWJ3wJ-Uo4kP=0eehP4S^l`ZYz3ES%e!pO{=0PY&c$ne^01>kz@_ zFK`2kkirHjy|llbkrRFGL!HEQbRe@dwX8crpw4_f{gDLua5&x@%SQ9rSSp`ui?=or z8>yajYe&3eR$PeND3Rpxt@LAOgy=Gd_V3N{O#eVEn`~`2Nd2MyWPiMWz#qA(FPZMi z_cE?OLO7DoM1{xY14(K)fbnpc@KWh~G%sj|+^o)gQ(qL^2soXA;S1S1gwd*F`&{{WReHgZ-`TAYdw)O zL&TEv`#H8O@aM(!c8Q;tm;O1?+LB7M_U4xdwvcF@c>G{0nUBtm%@rh))j3k#(`|6CmZXJX3W&gH5&G$5t^ZMOQN-+k#Jw8hg8G;D$iH`wdDKLAk5N8bvjO@ zGXrg%Ir@M3hQ4GjNB?f^jJ45U1F=-LZ5IF3+S&@{NovkS;I}+jBy*Y($-ZPfAI|05 z$ON=nLEyBj8l7aKgcb$S)Nu>YtH9TwX;r=! zZpe|H$qjbp@~Qk_-q`0{XFZ&XDnc2hO)YEf(06jNPPPu1`l8%s>#9c8Gi$@xx#<;rSnBL>z7!B14pjvAcIH-rUY`v}p<3t-NWhvmt7H zV1T@fX@ny^#B)B`KhPH=IlJi%LrcU4^GMPEF(bj|u9y`giHaE~8M>L}!L7RUI`|bg zTJ;c3^XR`%yasDt_{A-SCMUk5crqVL^@StZWOqD6ZZA5J&$i9&tcynK#Cos`j>a=- zLQ5yJt&X-y-wO0q3vIY1i;*<#l~SSUK)6Rp;o_$2;v7MnsH?~*mc%YCOgCBYj4w&l zJEq0#M(X03f#p#X3`Cs~Y;B+087;_y3;<1Co?^40eZ_57KG^j%iN&SYfS8y{F}6ak zzA4|E%`7c+CdvyETJo4^KA-AJafHMM$h9OXn2-8cdO6}isJnr9L=GGxQD>xrhWSks z^Vv|Zy7Jpz?P5qnZfR_Qe1LhEA_e}lt=+{!I80VAp6t!^(Q>V|b*N*0w6oD_o}>Ym zFi=dnk?f^L$}Vt&SznliSeq+U<2O7_*-Bi5;L_Wo--`R`rH#p?Y8Bx~oER|Cc*D}( zm{(Eiy9d*8<5GA{;~k~2^&84?)uA~OBgd6U=JMGL zmK{*vW@g&qjH4IjtSGXlAK3PLd`%TJMVB)A~Q&7k?24+8BgUXuxV{=;drEr z*2Ard4oMFTEH9Xn5mDyo%uwz~^jAeP$;?I?lgskSbRtPATY~Fk$KqPkF7Tan(T04( zO?|x1j^?tINHF;lN+g6E;=RfE5}IT~$!x3#%W_eK;P(=|(oiY581~a#3Z~Bk09aN)q%=8C3~<%?j@9zJ=>OUE&M~k{%jc*lz^2 zX|GNC-Hv8|sxUgJ@z1eFd<6b?|+jAW{(S7``Z z^VCdVW-y!cB2F3X?xqESyxg#m)}G*$yR3DMFvm!xDb2MrEX)uRBwz&ijEtzoZ|lS%j&Emcq|DWKuU0wB^VSuoOz#yC~3 zxSRC9i9ssDM3)Wp7$d^zM`nnTvQ!pGw8l-uM1MD#tX#IW-vA19!=M|kH$s|BS@Y$z zMhu6^a%uM|A>0xhq*@Hy1LsvUfBb*(8Z%DzQc10?-FcN$)tu~|I53#&CC=kZSOsNW z9jdqVgas+}$=m+S*3%&{C8e^?!|1}IDgy8qSs;2L6s)#``*F=<0c!3ztrc5nG zJrI@dhRlR&(*VltCpaxu>}mYyQJH{MsKJxnSJGYdQ_E8`l?uiyv|jXJD{0H z6L@kxjWd6wkYQImN)w&rY9@KW>t6KET)Z`0uN^g%)w6fz2m0FLWD%@ly{RpPrHos(n(ZuxFUY9 zM=1_pPPOq=KHkTkxt&5_QUq(+48t96kZG6dCU2aK_4|z}C-sRA=fI+EnOt<Xn#pxlBcv(4t#9|`JmPgZUX#(9j@tEN=6_;l}`EfzqP9bV~sg- zC>$}CV1*d%Fe3BLypnXA(wTg!o08FfFET$tkuZ;oEC*!G7>VWDXd-mXnjbY2wVL-x zhllkZTMOq!Uvt?MWqUaz7RyeJ<>IkKQjBIeazg)X$B-g=s7R$WI0&*sUePPIA8*FR z#D_X${pkuB9GGF7H#4QWQ%UUrkBKk25?({s{(kRKWX#JDChG($1z2Z3O%uS@_qYVS!yU=CR{LX-?hP`z@FK<;{J)dVPm7|_z;gcMeV$Cj8f#Z zmnlzsVRTCvy;-Gippul9*uzb!G`X1+l@78!v>zs&hld0|ML$C^=F`@Z;&;KLDI($D z-Mp8|&8x2tgqz9wCe!gD)*Okx$pAJ^9hwu%Q*c^<&g)uC@gU0k8mBc)C1s4~Il|+Z z+Bod^5G~j`X>(U!(ggN}NYcXgE-9q^6o_1ET1+&lSYAZ7wwtvib-=7cSd_ZH73qp= zHa`-8*UIg^j3xLD(^GwYt&7`d@mjh7)>oZa-H4_$nV%NR$2fu?%JU*OOaG*aJxF@Hj0Tvh z0@;2lw4`XSBxSy`ZS6|lX^&QPJcwpn&wwuARdg+>Tw6MqB1_mon!%|Gmd%Ko7-+>t z!hp`yQyD<|TWF?_)}~|&5HL4bFm_d1wK9d_s^boPdq<5B*H5-aC zQ{y#EN?Y|r&y^T)Yc>s7zq9Hnh$&p3PA*kzMT1?ykr!a}3%W+zI%w$0FBVoX;Yf6W zS^b$@1@GY!jPS(hoG2~nqw@y}Etqklm2`BP)EV2_&Ay)@D)ok=9rPwe#~OkK&@HsA z`rtH)iQkz|9#8(mt##pOG@0h)Vl>s=c62UFrSWJql{4E_d7V#cAaQ(GYg1G=rjqjs zh_kqh9By?^HR7kWifh*KU$ikuQeidNq(|YUZg)-5#-KJ@H_Yy;a}5D8!!f8L@t)WX zxM$GSl9wGvSw_4o(ODgjlu`?+pv%;;;z3HRr^DDV$ppzTQbNDoN9MGplI=opGgaG&X=mskX z$xM{Py_vVrHxJYiVTGG3IeuN5%+fBWLGp#pKFdmX^%guRg%#uy)si?tfOo32%5Hp# zPAhwZ;sIHYY5mUWA?H|wTXYrpF6_~<=4#wf|tf2J`(b+_*5cYF;Pbx3{4Jds?%9K=8V`x%&3oA}0z@*Sy>ZZ~$^@y9H$dg)f zEe3Qzv|3Y;XMJ>vtXHv2kZO+eyS`XCOTIZyDUW!08un0@X`$w08Pr~_2Q#Q0do*)R zu>s2WP(VT6mM0u+n_Z)-pt#bGT$WJaU9?lfW*y1-RTt@qd!r}E=(Ny8INWV0a>Zcovc4c7RVE;#9_AlG>uYO}2>Q#mXAiQ7@#0BPK1(66T6#I7+!a0yXpBT=R}nvaHkORNeW%avdz) z40oM1loA7l+@W^CNdS{t2?JC#H4B8!d?XU36PR2Krqd6UFBfq~V}-0SCAmrcUGJF| zh!h)amu~xwN-@)}l(|Ir$l{NL5SOTBS>2hZe0P;)G*`>TNnmHmYAKPEX)VAx2dGn? z)1o<7G+4l5R@t2!gw_Jwyj{MvB4y2?TvVXsZNbR|dos;NS7b>O+OkJK`8RaBdHOunZ+R)`tYBe-KEmudEM zuAKQTCIGPnGf)@@tYSx!3vH%t)VxJla?>>+$lBoA?_p=-3VW`lGir&m2^hU|t zIXB@TH5QZ_3^&lo#?3xrvAfi+ljVyB5oLAg&19CCI8hWfIH%{%3tA3Zm#!mC)D_5D z@rQo{J{yqz6M@0Oi$7t%tK{ARsztxhYoxSI z;MSxI8{bqS1#OyO^r!>}X!?W1h$i#sf?6?X5V~i%qP?QMV=P^QU|O@RR7t~mgQQJ%%`1{=25@`_2k zMtG4%?#7*X)YI;CX4SPH z9h?@WXx)q^giqI7dT6uG!)Ai6VxdFX)G<0!?aQi*L>W$LD?4-Q+Pn@#cH}(y4J@PO%lPU;sScqDUhGPmdG`1Xz&rq{`ch@-)~e(4wGPuUG})qS;?x#{X4L zyVNuM-tSfad@Uv4Z)2>ONY`qV&_*&Gc;xEWP7S36cp)b zvWzr=bK(W&xOtju>S`UfjK*7URf^{~WZExDb(hXJC~hHZO$L^8)e=KQ%PCe5*uX0 zjfoT=%%u(CNoU98M9%W+`k-VbB23&l*=LSOX=f1C3A{;qJYCxu(8JkhKd;%Hd{)UrwJpXXz_Xp=Dw+I?W{+~t#mE}P7OZCRmU*w<$w~ZReDcVS110-Kf5F9-e8t;Fr>p#djr3dr zHR{z$bYQcn07veh-J0wrE73xwWelVIQObU0sW_48wzrwLQ>=l;YLJT!^F?~Td?HG7 zkj@O^+F<`W#s~(6%EFYtCAD;q4>s0%$Hze|KT6fIUv{u+R;OqpwQ!Cn)j-WSdF$Tl z9dHVP>g*j(R@Zk&vv(r!l9qS5dd* z09MS}K;g(k#qZG6rNtiaq%x_lB3D^WAJJ zf5KCYj!|NVyyp##JA*?g7kNeYHtOV0Xbt2F16}W#fJ5iFvKJ((B1i1$PVr`|;@uza z7hGJlS^;yR=vAt;N`=cxN~@LhipP)#rD!HvU2yU2$tlsEOEs0j!{uLAqnlidvXA~X zN%u;`pH>y5$}VI4Td0CtYfKwmiQJN_ApeFVmG`Z%7IrT(t&#L^#jkro1s>Ow^C#xR zaUiW44o6TM8-6^3T6PTxjCYa77u^R+TP)nxzJeDZ!k`w4t8KjTfs0;+tEh`wDSFAZ z`+TC_u^nz3qS>s&;u zwCD7Si@vwxrmSc6TWgc_8#C@{%FQ>`3pretA=4TgeYr|*50}f6F{5@Rg;H0-4Kk=mHD6pCC@z7V-6T*NYj=HdjO8M(axf^o%z$$dlm?t@k(CZOz2X`f?|_@?XuyEeZ#>|hrrZNgMX=fkmWIeQ z(q<~G<$Z3^%q}Xm`gzw%-m2JgS3t}%(S!>4{bqD zJiodIkB=M`zKx&-JwKA_Cw+hO7(Fjdy{AgvE0j|CJP?Jg{7Dd2EjLfT6Uf78@#Jw4 zChhbm?84z>n2kh%eaUiX;a5{6)ni13V>OU^iEu?LnJP@ODh>!TG+cPqBuoc(T=`{v z!{~s?;+ajNuA&Fu0?UQaD5@Wx{Jl5hZ$9_uf2UCkT__xN?lqz|>gbXd^AQxeVN$-p zBo$6`!@x4S%7#rEWgC!i2%gc}iIze+vVE2@N9EsfC7FxP75J{X(U@xotE=E@Oday) z(n+7%+UzbG1X}N-R4SWr+yh-c(JX432G3O%G-aE1 zZGew)X)UZVO5?)rt?W!JH~z(fa}U21iJXID?orqIY7L)J_97uFa%BUdg+V`QD8I#Z zL6QZ}{z@l?vP82=72J_(@bo5|9FXatU&vVV&V8drh2ur^!w~(#qg8_pcey-}Hv^1Z zke$BgY?Pf2vR+i{UqTd~T(c9?lzO44j^HI>=Vq{uFCn!m>pRs5v=I?Wa#<5-8pxIOg=9|6HY`Q4l29e8qYC96y$Wz_FzgULja z$(UHU)X3cQV?N`NO?JilVzhs$E8wgfP4kXUSm2Rz=RV@1vyd#PpV;KPsT3D>$-YrC zULCW{^}PWvc;$@R2H`q9)0O}_^T9WVmPnd=UPz_OzhIK3xGc&lOI0~#E3A`NN!4tD ztGHfQEpfm4lOynviKEh*Qc!c17E-w#x%behMd0KfX*-3Zh^0zoo?^vR+NNHvybAv8A zbh0#R)^~-xU-5a{YDl`1awDT8y_Fr2G9*4XEMk`cXV=Vkox@e}im1(4j8Xy^VJmK# zG~;^X!YBm|4lT~924IhGWMUBkQndVFHf>amHx$VCbV*YrCn2(nG~m7XV3v*o^RSJ@rB@f`16EVWtDu+P>$FG{<^4fu7(Ri9S-?6BMx^s=he8-6v34f$57)9{) z5vejJn1A<}L9dZD)t5jMoGNL8Q)Nvsz3*vzM5d8Wl=o4JxF?-V&?i@0yCfA;KHR9F z!ciu!sDOeAAk4J!3#uw0U?K%7U&j0C!*J?KywwdKOYbREjLgb=NYU3Dj9VGLg}2DL zEm`sG2%K&fl^R=ii@Nz_1zDaNTJ@q9+;Rx8==MARN3FTdrd$c;F?1uet_Q!*ke zZc(nW1uvp*20hqNAr z0Nv*ttvyrPx58WOY{-*Q4NK~KrY6i^(~%!)aygyf@iJGw*{{kOYNv9I`|Qgnw-H51 za+|c*$uqk0)gCajS;3)*YE!vBcOuCGG58QfwM`6H&;@Pr$h(2%EekQXef6#V`(K!q zsAg}ndK!0Iwi)ndYdwik&-M-fe4NkTR^QC0H)j?0UL;j95zo4#JQ4o{UbU&IMz%Fv$9u_#^8EE8F&DtZa;e4HHHvRU3aaiQMIMZvz<9}$((aMjxwI+n*{FDB02h0#6TZ??78f*={Sk1mACuQej3?|fSxC54o1BJtmifKuNJCU7Too%TA0E}|)P_I#f_hE)!$;Wz z`EzHHhLOgR)ul1H^M~r9>4v%zf*oO7kaaon)TWhS^%yCA4Dtq-R%Oamo8I`FOS-OU z1m@C7m6b4;UTfAY)+wK%jZlT87v}=#gGWn}1*ns^MR4XN(;{TpG&*#65fSf=W%aW5 zcl2x>s}zgRy#L5qS{w3_nK z6@_f)baEE7xWmm^yyLWj{bu9H-S#aCxG|%w~4<{-j~#Ir$nXzn&ak^@Nu)$q|f9I=91BFT7c2@nfaFV zVE@2inm*OSTN~(j1?3?0J)`zsl$M@sW^f>t?!mIPGnZP{YAzq=;twdW$gVXLfPilm`GmhWv$<#@@;D^^;0 zI+|pDYv$OmE0yP8Q$@eho3!Bde^V8)&QKQ>lqUGQ*j#f@$MPw0c;2?GA4b1a+6_x30AsW@+1pvfv598=DRoh1_P z%)5kFTf&aqYe`nu9X^?c5dVU&Xw9R5@`4>n`h>3EyV5PP+ED1M@`kow-K+nIhjx^74mJ))u)=O zk#A$(zSTsPeA^keI{8s^t7hO?Z0`?VA8!4IH3PKN`=e|+GgUI*-(91HdFXv#*Y3Lc z%Ka;Ooq}ic{t(PB?Hdi|H-SxZLHwG$xHDrU7h^Sy#H}B{oZNh#nJt-GzCG_CY}8m%13*XeFMoXMedCQu`C_IbuI-rK|Ib~(=vvt^L+BCI=R%- z7ccvkQ`NRRHrSUh(5{L~Q#zARbuXut1tl_hTDY{myyAE#Kn3{TIZ^(Fre&1~uBsk~ z>twLZZf;gZN#<3dkG}6$s#Xx0Cxcj47uA+j+=$u+jgv~Zpf|%*CIiB*+62%$!!-f& z>aa`zzdCFaz%N&B0*bz^5gz&UBo0O}J?ZVLrYGZ9H9eWV8c$CmIil$q{C-6oPlfNocg^OnNswXJFG~5}AcZW4a&AY>%qvq}5PEzyo$Y&{&8NoE= z*Q=VR=7p*zs^PH4GnHwMXsVVVP|-9pVyJqunzyQ%t>y)tt}Pm5+MToZ}Jy67Z9EKZw>C|AbYigMBZ*Z|M!;J3m>_vw|vZ}5hpUhLvkrKj;` z-u3HjRiZR?pD{TYi{f7`o%KOb9igUO4`c>}NaWoOx= zp^Z2B;_efNv!2WQEP)iAlS1yu+?L}eG||B{6c%XHc2pIqOQmTDQi*70AWwUjkOp;= zDprlacdBc}8js3YQ^yq)_(dXewrwe;cePKv`g4t7wXa6%bAvP&Qu)DrGHSM&$tTcq ze8Nm_(+lc&xXB2Ya^xgh!8!jl*Wsj~dU2PQA9%Eh9dJ zP)a`T#Eo1-NM}9W1o)n!Txl7*X-GQC5u5ubUXdF^g9G6%a@ql|^6`X>7@-a_gbw_?|1B*9l* zcwLLwcLt=i(Evtb}z_kmsXg9wWMoJX+N6FT9RP++L=@) zXU+jMw9)l(g(9{WE`G>-{VSHIJ79S%=w;d>H$X|QAhin9fJy}R~m~xvjXBk2@1OFbzn@us?k?q2o(0>v&sbyg%?$05in9yZ%oQc(M4l) zF8%+BrhaDC*n?;7NUtOCX_Dfc#$^9Mez|0o10-J`%bHyPoq4(sAyF-+c#$?m! zKH~ZO4KLa%%3l~UM}qLt=G?$+jj1pMg&R=$l2qDD((cLnB9!xhvv*B!i|Z+ z{{H2y(}#vyJ=yRg^gcckz~jyvRqPyh1s!iel$UH{pE~59GpBCTthIzfqua{4be^#M z--+~JIy%5>vmyzQ=dVx#iRvUk=#B&ehPKc{cH7efc>3EWIz zQ(8wCBKm0x^MU#lyGhDp>QOwq5`52~`Or<=Y||vR{tq#grB8a(vas6V&?npP3JiU7YTemP z+7#4H+8rY4%4ALMT@(%Hhaz?E;5VAcm~u%Q2f^WH&rh5^u+oP`L9vt!#QMAM{|G{K zoj8R07e&Sa1!s2~P71y#S6&FyIC{m6u*imL1%i^~1F=+=6YWJAbGl!M*H-2dEV166 zZ){b}Z25i`53;+50mAWlseDWRYmEw83wW`(#bWys=q8IK=)d^^S6#~Cb*I#@0orl9 zwGBXCbjWl=BlY4|D!2EQO3$PDwYdwq@}}J)4TuyfCN|>e!F_W^?QTu3nE&92!edv8 zbz;O5sD@ES<-J9twTV0`Z`P%8rM(=dJW6@Fs@9MNU!zmo=D4V)&Gi6TRnqF(^92cY zO5}a2phoGL4qVF3hr9nXh464ar{?h4zD!m!o24Y@T$NBo&s?AQgZt)X`fw=eMEK9i zr|A3Y_Q7_P1WL)wm5G?<={ywRAB@CmObKW zhkN&sA4TN7=^#M3X*f3!`O-vADRAuQZ?$2I)q{^3!DcoIzsk~tp4F1i!#aQ8D!I#kgPZkQkyl?nLf?u;Wv{{wRNhk8%FpC4f z9(pFJUZ2w>moMhB@u+;on)gkH8>DU>r;ER`v7V&6TCXdLCQXh}IVwrz@4i$&Ro4?y zqU5(Z&ul2_%e7Jcnd;VDnWxHioGR3GJx;-NjD&cW4osMRQ-NNmVk7FG=}})@rhqZx zR$PHr!?5nnwe>HkJ7raV9~6N=-G4L@H;%70#6uZ{^`h)olld zEE}ZJ+Q)rW^teK0-hdr1oEs>c>Nj6C&{TgwD#RrGy_@~%FoCseo{tyEYO=*_mMT;m zDlHrsR`lZ_L9A5yDFflieKFxkeMf@bkey2yPKu?noh4O#A6(~{t*SoxH2)8XH_#Ar z=_&h^A)3$~sFm*66ebP1Twm9Dr|3#XEEPwdzFpXG!JuDr z>K-?EAn4!th7STuwyVymIO#L|I4GdO4IliKZn&J%ZlDfB!Xt@q_~SxZ_lHS4=HozG zj@I$%o_w!+iSKjvuj2U_wAK{+Tkd;SyaA=6c+`ZH8jl8rl$BC*Ibb;=)FdZMB*tvw z3#NTH#d2g^I%upoz~+w-WiuIE0%8@H3h}`IQ+j+oKAi)h5wZ(-B#8FT$ygnXcr@r3 zW0WpOO!W`;4{Hy2#X@3Dqf2L&4Zo#o7cE9@WziBm##It^jfQA%vs-(c1GSeAhm_IY zDmkfCiAO}%4rpDIqe{A^PgD(`E{h>}u8`QExCojDS_kHmA;*LC-0 zVtI2r3}0QEri?UyAeFv+mdvJOv?DVSAJK}||ErosE9O#bnPDs{oe$~OnyxN5*<;Z< zEmFxkt@;&KC856C<9qZVj1NB1rR?QC_|(-whtTNAHhq_5gFAa9%*r`?|4_hXEzCw+ zLrhAR!Lxj%@d;V}IW!Sc`4pWKJONdjnlwiSjPF#(A)^47Z>C+)F00OJElMG#@Om*L z$?{&T?65fe&~nYtl&z4#;&NWFLsC9m>AjMKU1^XTu5ys7Z?*hb5qmWqtHQx6)(j`! z^B&RjPWeVDGxC%-_MFX0RI z*8Op$LYJxMh5w_kB)OA|MhHr*u^LMVGM0=nfp3FnphhaIv`55YTaHKGIzUkLHa6kC6h8lw|hur#BvM_!N-) z8vy^gR=wZHsO7gmDv6^!A2_M$$3QA;-P`+`d>y2+hS_PA+8tAIPRci{$FpTas8CP> z%rlJt;g-EaxFHp|qTX*%B@X7mD}@cB$ia=*Oqm0lsFgzdRnKa#y#B3thp3i{>ffHr zpVU+-{af?)t|kiT-_Wp?&6gaTVdpB&4e#R(^Cj9FvDx1+oe7+mxMnuEPF8V;0-LDW z2>Fix@H^m3&cm!72?TVJZChZLs@7#UE&I%+qhz(e8?(Y5^EwlYoejf>@7SQt;(I{{ z=oTkhn$Y3+bUbOUkDS%8kTOJ#vtwOJ+~y^ambTpFIDfQL7LfuBhud;(>3H8@&gX~L zWqv$I{rVh;9qa`0LpgYs2#^}Sc zL?^dAN0EIP7{Fn-5PE*GZCSAlLg$x>{$?3i^=dv?S1RGt-(^Y64T~XSwo%H-F+(;Um zK80P1P!~vrX*Fr?5VI0!73?qKPVkj-CJ{57*E^$2k^z-SIYLKiDepzVbT?-~>H$I^ z5&2!Ggp2XKdCm%Y+1Qn&&(1+fDcj{Q`Q-7;n50jt7X_7J9DR_=tfNtdWE^GA3w_ry z4q(S;bOSK^G5@M(x`~Re&iMK8E6P|>2_*v-B-84&+2n#ppv^7R9lEEFrlN0YT-7H) zjMS4_Djj`Wp3=c&sp(S^oV#>sefg2Eu_OYA*7>1QtH%dt`HZ#cQMvSOu63d@f7!u! zo@AR--LEQLNV&%1&$n0iwQeTi{hao!aNX2Qx;xd=mQVJ_hq_=J+|Y1jN+v@&!1My6 zQKqlfYboE?+Nd1blgtLcrXOtdwl+<&zQM22wV!_Ng*(j^l&<%hW@mbcf#!MUJ1;rX z>l8gKeB>N$gm4)I-F9oer}a&M8@rSFI5sZ>H}Z7Qv~tFu zp(H-dot(;lYp6Rz_nx|5Z|qABQKUmBjQE2o=}gq@w51>-#0Q|V*-X}j+(O|*J6+P5 z=LBs$m7*-~35*xd4H$gR+BazAs9VRCYQ3En_KgGtz+P=tkEheg8B^ z-xdXkDk!vTYiSOD8eL?7{>^a~USK^GW*T_* zu~cFN*#vzqK=^1(W_exz#9zmFf5e~lQ!>l6Rr7DO+1#G#Ti%mNx6qfd;*-hc(A(L} zVA_m|{zzpY`gJOOkwK$#{e?)T+Gk12ED8rscEJrt^V%_Rpnp1V8Q*1ks-RdW&uRvR z!`YrL-8!<^2;QM848TM=#68ei46dJ@QQ6^7m6rK)M#}T+jFkJ=#-maR-C${mHO)w- zdU{c1Q+`#(&fk#pECqxkH23EY_M4&AZwBj+E%clDK@`h*$;G##))$y{K(jN-umdXe zK|!8=DA3avtd*Lk40d-Xv#pDzBxTl5jZ?|3@#QG}$$t8*2M_tI#?~Ryj7XdMCi%N* zI^Cw6L54RZ2n@8S?HmoJ4k}1Rtm$#b^Pv!%E6swEfl`S?Z&} zB$-&;AL1{QFN>0qpe;>39Djuy2&D){~WGow%hu9V6=>m3*~UbWM;1Lo7{kJsM42^vGFQLA44y26Rul4 z&=ZZv^+R@GQosot+|0-nWKg&{kf%+J{XJcS-5mcpy;HXUj_TT+Rz;!$*Vq<+nHa4= zqospVcaEx?p?6**#V8yf#Hc{Uq03nCD-lHleP-Kb@gODzcuHGk$Tsgu@XPi z%cXv%Zw+}H_7aczv`sPq(?oiCi>K`-Bcei|yiI$4En>{`YY|`GUv0J;y`uCs>;AE* zRrilYje35x+iY^RStN(lvgSRghPevQMQ^~#r4|S})w==rf#0@174X>3T8onz+ zu+fN`D;8h_TFxWVyZsp;_?*p^wnF0%TI*Tgilz3PZ9Wv>5W6W@yPTEDGKCSu?Fci9X^Lz{X+h^x1Cf{e~lCz zT*K6CX22+|4eKzAwF0!+gm1CsW?d;O3DL#IDeU$HTtIJ}lg!f9IVla2fa`)9eHQS< z8MGp#i0A)f@807gFYEq~k9b0~oG=TiY$7ehv{`f&$!bzpSv*a6LQHp--BlL%FtWRf zm^tAg!mJ6ikWM3=h{{IFL`<9PM3^>W8Eu*4c49WGk+KLgf7kmn4D;GuW<}Tgub+EA z?)&!no{P`-`d-&H-#LH3?p2}vLH4E7>~JhTNsonAfA$GiZk!gau$R`^SAN?(l-Imx z-MaPedA{D3Ug18(vL<{%cHG(S^3(3UrL`Km6>D-$JbGJe%|>^d-ekGh{$p;a7cDwz zRess&nNoGN?r!d#6un8aOoy{&xkJ8t0`3E~cl60?+@i}~WGDOj_bfN8 z?!`#H?xN#P!sEtCtKD6xZT6LLc1~{6y)Rx&L>7VCTJu{lUc@b`Qf46w? z;@M}RxfMO{?K>%O%<~k;-kvLfcXd~-oP8%zuQg`>GkYO*`vBR!Y3-&WcX6)lJC^QI zWQ}&+-W1M88{BF4SGc2ov%7DvyJYSm%{@k3xo*X>jqCLmfDbrwrlUM z@HyAq9WdOJ0?+CV%Qw15z5IUXUj5JZj#H%(IU&Ut7Mx2KDOC?3YHr+JBZHq+kJ&%4IV9cJ0=1=%jvL!Uhz)lJ9ZCimF6Z2dMjXYXmQ zb@oo>rqVq@bQj8NTb6$%oZI0VeRj0t{`wVjcirS?C;1F_p*?pm)Q`B$!n@ z0v($vw}*p<$J47|vZnjw>bq!JS){*)Jr_4tnl0G501z?k24(9SmH@+{b3y zwbNlh4bFCV9-HsnJ#*)G<@_B#{{gY?%XV>!Q+0RW{)bpNS5@}DK6|RF7qZdWciD4Y z+}Xk7c{=F2Q25*hh5NVDEzb20qmVmBZ8J2vLsD)(c0Sa)miZNKc{njH?HJOA6G z=Dxb4AAimFtrkw%lI#~;vPb9z{ek<^g3X_6Y?nxXo(F&$_f-=2c;}wQ=Kd;sv2b^l zW_{;J?_+9}Z!=h0$Zm<-AsG)GJKyizx3>!HwEMxZtC#!5XSU}%o7$aE!Os5j1x$c@ z$a_KK@7nJ${5$K)c7vZED$J73HTto}S} zd4W|54c7B4=j=Y4ca+_yr&%a;K^RT?Y{o0i!xxh{A!irqr7G8=4xzPJ?!CySRh!-LD6A!+9 zGvDt=-2KR%W3D0l9c}mK$Me5W;~uFB6v`f77V?0n!=4@}3%$=Xd+*-Wr*B8w`=q(I zd$v7Y=r)Jz?61Cd`m|-CGq|YQJ&@R8cg& zCp+%r&!z5(iF*o{d+SS&ye@Dj)XqQA)8~2fK7MGSJkOK61&`9azfXK=CO|&|TC?in zjU4}lF3S0Sto9;?6UV&*WBJ1FE8+Z`mJ8hzd+2Z<@426Mu5jPCn|-3SOOH|uIXEr! zn5v(jy|l-s?33tSJ~XM!i$5|gaQ7ETUKysaWfyX2F7xNyDcH#Ba-1F|8Kb6%J4ZXIu=K#B~ zx!I?~?s0Mcix1mt)SxaZJof?Cu00;Vz{}3^0iRc(o&Cat1__@owexwlrn@xFs_?wC>>4d#k{5WNe6g2Vclj^L(_)@wB6lz-Fr>?t+LtJn*SYX{3xES0>zTmas{wB8+Ufj`tn}_aQeJ9{~uT-_o!{huHty<(> zC+jVXd9RITPXKbC;O%UOw|N+zegAuB?RPksZPU~3uY|QYdnK$FSI|w_+;gQu1HQlo zw(#-Ry>#AdgzbE|-JiXX(OzKl!h@}`+3u=ivtzxB&!M(EjQrm`blKy$zKFP>6QgXi z!nQd_iXI8(zC@c{$RJ60M79Mrm?QKtaw6O1R<_`G_Y(4k6>hpi6aQn)7)7SkBZ^Ke|(AaLd=a$^u zm#*D0aYKiDL)V>8NWYHQaNg>TEy`xU9DUZt9lo(YHx)a6&s=|KUo@ZR&yEYb?{zP0 zUcTZ|JrBwKvSYrlqvxtDs@8Y(k2yN~E4kbsowXr++7f*kQa|Wi>3(XkVx!(5S#*@X zC%z%PYQ?gZt1rGdSd*i^o|!xI+>ZN_`w)Mldyny4S8Bccy0F{mQa1o@Ws97=tx zwL)i1ai6WMTax>s#5^;?*B1G1tX*wgooA~{bTXEC2E%@;vSiU>EyY!BtK2!d?9xtJ z`R-Z33A10;&dfE=OW`CO0v1;YAwd*f;=eNArt%OzW zD^`U!E?Yi3ptI{SJFG`(WE zCQEODo}Lfgb)pv?mAeaNXUL6~{ki+7%6;M9tyUXm9k#S&mo2YedRntzXWVlKl_hRi z-6&(}&NC9*ogNQUaMZe0SLAnE2aO#b%-#3Zs<)qa>($&`Z{Xdh!A-sElYK)M8+rk= zW>4a>vzA>(xqH7GI(Ly34yVRpiN3*L_wej7HaqNYk?uI`XXL}34ZGXj`G$RGqmDf- zu&VQOkYAJdt9d43n+JHeS2f$-_teD#hc7o}{`vO7_CRCi8XVK+eiFET?Xu-7R=9`h zxr4Y}3dJ4wIRds7U3n>ccV4W^py*DS-ON0_vT0F~>}^)dis+;AY!P=w7klH?=JZ5; z%&OB!x&`Q#;N^Oc_*B=i zjkhn@c4e-dI}^mZmF@?&*|nJM>0E2~U4fOk;W`5?-D;R^sYk!L3N}o+v9`a(kf2%a zLz%fhJo*avj1NO&f2&L*lmEkPv;62-GaH;jZEb+^1&+}vEZt=v^D}29vgx+lI5Oe5u@`$+e%o9QiC4 zEn1tsL!Io-R%S%L%p@D!fp*ngnmy(39Ia7q z;&OkfZem+UU#e55vO{Hr^~BW=FSu9cEp`Xbelcdv6=ns z{P~+@4_@09J9d+8(6)D0c1c?2w%cg6AMH+6Lb-EnsH+zHnjar2J-ipyuu)x1qF zR%fj zw)HD;gFCf=`|_L%-Fa%(E}K1@hHhVUUYIklOyP-zm>|s=aHPT6t z1iP`r+NqiQ-TjKg4;PQIQgi=x$%+-rHq14%9v$P(C4F(bJLbCw$yGY@f^)Nb);oJP z4);TA&nYLKxa=smLH+-uk5vCoIc@0)CoZdYW3za>zAjr-<8e3E2bY|(tR~m8vC;kg z(MK*?>^ZTq@jWLjUAE}Rqp~%!x6IW$>d0!3{VVe9?%Bir@1CB$ocDJBzu5hk{#*Z7 z-pAc4@9zFb|MdUWes_1P{zolUMXmO9QnkI@|CZP-`Y-+U9(LPau9_14Q=YBsvD=jB zpDOR=+V5f2_i)J`&e=4(6}8OvN_qCbl&H3Mv3+A7KZkDOKZ|K@s@9lw3tt$VsE8WsKDY#+2&x&6#m%WZQH*W>JXY24Ir z^*B4C+Mj)$wBH&7k7vKxKB#4WAGP<|!alB*wz7}Sh5jo$3fX?|lm9SsV7(Yp}Jr{ZF_(_3VT0 z#oXSWYjFD^JJjC`^>_C?JNx$mSAW&?r;0r875a^{fAh#UFLf^+_we-1dgEa|#d>}C zrMdb=o=0c@-u?M(|M#@|8iTfjv_D0jJ7(KYFRfHFw}tG#;K#GC$vySk<~NOI^WyFD zJ^z_~t?Jz_-*>rQ;d(q}+vQWY>y@g<ThOuzhk_HrJ>#A4Z*a)Guz% zw`ZO}`?sR~DDwa1I_ds@1pV12e{a5@%#)}y?N)s5-vsjN>{7FvGRR+@T~d}$BmZG` z30hu>{zOsVkKBv)HOMc*b_2+toxQ7Q13~2PckRn;s~%6|c6rxq9>Tn+eePci+BYJP z7Rbxa%8w`8htWQW{cT77RQ8Z(o9;y(z<$M${~dLb$W!QN@oD+~Fb@>SeOPa7KY{v_ zn3vw=+4`Dt<|(v~qWvWD=g`j>`or9V^~pSgI&G*wjr?Yej~DfavE4G{O~~tzUxqx0 zd_Cr+5&2`q_fK68#Ay|1IjYBX36@L4FD9bRmBQj{gJ58&D^Xd<~8>!^jUr zoM`GRwkgvgh#gVT>`vmf8Y?(0&qm4BPc!o%|Q$S&aMujDr{Xov2@lJdFPI7Rdd`KY;zMLH;lFCxHAM zjB_3GQshD8e?1W(E@pBKziEu#Q4`BzX5pw`7OBrR-T`qFXpKN zc?;@vVEh{~KFq^tpTIb@Bfkjw0P^QBk3Os)=79ovs6ZY^{Y$W(hmr4rd=mLbF`kv! zU*-b^^17z{IJ5m|fxHg$&h{SM-@k!=79)Qz@=D}Q=zk0P$$YXv-i3a$eKGpUysJQ7 zhyHv7{hUU9=0UVyi*?e7yc~H5`D?JwV+HbobMy1U_L1}E&nFAyiN^Wcw_v+RVm%KO z$m8e_+jn8R%rgb@QS^uH!`SXpj8D8kK8*gbeH7beK3yPBqCafkh3#H|d2GjeU>?W1 zVje}EN3pJYkza#+6nQ7|B=Q4re49Z2bsV2l$iIm3^x%H<3zzFXbNvex$Rh>vM1eel z;~VQI3gjL<&a%A^r zgYju_^O2jE5XOgjxIi8$kVgyT9^8*u-&-K}70A8s%O7W0$5$XP#{RCy_;`^=F%JF$ zd9Xkp!2YsMtU#V9kf#ddevAX_2MgpetSh$96v)f4UmwBoxd!S;kD~p3=w~t7$B@?{-y8GZg4}(4H}|g{`PXoN=|cV^wC_cJ z9O@4s-wopyNB)_)t$I9}0{JNN67(mDJcBxu$gjZo7h|2g6?qx*U&F}DkWV5%4cpBi z{~gBPi}wd+zXD>rP*)(26v(3(2i7S=`@_-C0jw+LKD7TS`tL{nD&#fD??xU(z8lvM z@^7L)UC8&vdWa&w7UR~7d<@5>81hSz$B}oqe&*KI@OF9E>;fvrc&dHw-zeJu9sS7^ z$ZPO?iS3hU|1pfu1oCR+)5r&~T@TjnQskA$uS1;{F zk$)BQJAk|m^D>J3X^e9c`QvCmf&6;p)5!meIvzZq-v|9EL;hOs7xE#j!^B0|*9+QJ zmLEmlgKD54jh4 z8}_RV`M=TLhx}V;Ux_@4{`-;lBdg}Ebt;j62zC6(H)4EhkS{`= z0P>Guf9sHc1N{ji{|V|hB437e-h%uS=x00f8&M~M{9Blp81hHZp8@2Hu-!QF9_;Th z@^7I(3FPD0?kMtMv`->mjs8y{{~_9^kne~7Od|g=+Gmh&!v0PpUxWSi;Cq|XsN+Tc z6Xa#c$BK+c{}n7>~945A5p&xc^Y{X`QMTEBKM*{G31@tuL0yYVcz4&JJ5a@`9HDU3_ef) z0rH92_Ua0jttW*X!+r&kBla{RM>jnoi9hMEz;x?uSVEe=GCre=)XOj68t- z@*@8z@-pPNBKINp=C|spME(Hw%a8n3XkUZ;UepgD|0L?vA^#BaAo3=xw?^a#U|off zzXx?%kT+x8!pKj+`e{f0GxR@#d=2V%A^#@oM3KK4?R$}zV%%cL&qF^4kk?{=d;`YEi~P0NZW;2U(B6mqY~+>5e}jJdk^d9@sX?B5k5HQrApacN*CAhz?FNza zduxrzi_kuV{1MDo3-bSByJ6&~W1QQOUyAh;L0*pW>_VQw_(YNa3+uTT`8CL6$iIkw z4j_LN{fr|&3)>w={yOwCf&ASVpHbvNoESFi}UOM4X9I$oS!dvk@I_rWyo*Gc74cOFrJmj-->bYBM+f{4f1zj90JG>M*r)O z{}}xVA`fAmHzGd|{Rtue6!I42pGN&K^1aZ$9r?*vhY{p&z`S%JzZvbL$e%*}UgWPp z9z*WO{th629mX?`yaW3+jC={&Cy=j0`%&cl93hGPjhL?q;I^gn?7 zc;t1+FGGKV$X8=MG$MZs@(}WV^rr>+E$Dw3`I*SukspF_iy*%b^}CS268jZJekkhn zB0mt@jUoRV>JK1)3+lv?Z@{<>BQHXo1oA$#A4Oh@{wI;Y72BOa{v-51h5Td4Cy{4Y zaJEqvds_1A|INsYkyoMrUgRg>epiP4FzlBP`IV?siTrrnFZ{?qjB&0( zz5?3~An!;2>ySTzIzi;Op+AkttI+=t@@G+}1^LI(pD=QMPqiKS)u)V74E+=&9gec{(pr!#mEoGdhjBD8}c&byP=;xL zC(zFtwKk5u1-+=v!BmWfE&oJ^kQ9ptFDCDEae~mgxCXn-U z+Z6I@^nVih9vIII@-pPp$d_V&J+1lme-!E$BR?9s7kLrpw+#7WwD%!D7voTg`~mdG zkNgabXAScEFm3_l58?h>hx{1iLF8XW-iZ8JxX7sZX z`ElrvANhlruNve(#eM~lS7Ez#$PdABAc(vO?HiGwjrt+v2cthN$WK8YM*eQ(?a2R% z?M9GqMBatG7UL5|{to25$X|nbi6I|Ee+H2M2kqm?H=zA6^5e1H1oDH?|54=cMEfN2 z8?hcHkiQG8?M*a}Cn?U|)Y8k)MtBp0)Y)e>UnDBR>WG_agrW=Bo_( z)2Q!5{tD!k$Zy7Y`jPYZ>@~<=kM;rNuf{s8L%tO2Cy2Zr`_+j2C)lqL@(A)4sgmy|L0(Ti;>r0{dkf8 z0d>ldpMn1PkgvpkRU&W1eEE@w(f=Cc1IPo&pTTzPke`V>h&+hA5&6m3uMqO@VY@BJ z--|k7J4?_KEX#wE3b_yYYUGv3KZO1ABX37ugS-cI0?6yp|2pJnVSNUXm*RNRi2Q7{4V(=;s9T^N^>IpN4s#ME*|nKZE>7xL;2rZ$a(}=hy$M(a&P! z&!WB;`C({ZhWsY<(}&!Lyb}367-v87voM}D$d{u|0C^+Etq%DL^goFFV$^R${&BPq zA%7U#Z9#rMwi`zNchql3{u_*c1bIF3F65ihpD6OfP`?*Be~%eMemLf90Qn&9UvcDz zVP1xjpNl#PaF-7e&Zpr29XpGN&&V|20Qqs~ zPaOGvnD=4iZ^Zo~f&3e&Gm88&Y&VJgO6=DJ@_kV!h5Q<{pG5v3`jbKa0rYg8VM*Zx`}Ep`TIY2cv#3@?{u@81j9w zUjxWPXdg#@KejuJd_DS^Kz;z)k0SpJ`k6%jB>FRf{9Md$3i)#Ma}xO?jAsUUGulrh z??(SU8}jRa9~|F`kspeFdXXS2KDQZ zHzN-szZ2u!h{k@|=g__v z`RN$981hEU?*Q`0kjIg?V4R1MzZ&C~K>l-VcNF>WP(O)$IreJ;c^Aefg}ff^Cz0QZ zan2zB4aR30`3U;&*_2=Zx1)VA^3@mzFY=#YzsiueqP-9KrN}FhzZd)KNB$K0Q-l2P z$OFhvL7h6}&ma#X=lN9{kzauJA>^Ad{w>HaM1R7_FGb#t{4~^wAb$nsr3?9WnBOS! z!_dAL`4ZHRAzzE}A3%N{<}r@E5B(oT{w}QZ1oBs){V4K&^goIG=NRV+X#w^659KauSfqYkw1WO@FNeS zeGT$&qJ9ARWoTcA{8Ws85cwYHe~9SDM${ib{(jVtBYz6xGmLy3YK1t;N zML#EyHzH3VzYFyzk(Z!-2Kg(||7ql}NA79Qum2?K7bE{V+Ix|AV86Rz+u-!@I-$9;1{wCC!Mt%+Y>A5n${vSd6V&oCD_ag7cew88rAlmzo zAB%afM4rZW{m8FHof_mH!MFvGUx)T}$gf8pM1BFb+lc%hs2@W9S?q5M@-wjB!pP4? z{dVLxpg$4h)2QEtdd|F^>u4mFUkX z@^>OnBL6VzPay9`oj@=4_PVSF;k--mISM*c61gQp|E{(ac5V&uD{|6b%jLY*?? z|3-g&$UlPqS0XP)eLwOqqkawYH2N7pUXD6-$j?L`M1CFSy%G5cwi`lTg*q+Bli1%d z@(WSF9r-vOry|I2!uWI{UyJ@kk$(a8dy#(@{fQyJ2kT(~`R~!6IP%Y;{xI@SAx|JL zMx9aQ7a~t0|1|1MApa=FA%*;7$S0A%19dXUZ^5`tBmWO_&sF*L|6`0>G4fWl_agTo zFGIdRav$wumP`?iO5avCIyaN4fL|%+KA>^M#`xfN? zL>@-|3Cw#t@~6>0g8bu{-!A0Gq5o0jJ!s#H{QcN&4EbXi=KV}$S08h8~slq-vj-eM1C{IA%pw^^k*9R`!Eik_vhFDBiL>+ z@(PT<7x|fJUxxfuSf4)R<;W|MUxWI7~(_BL5)r81kPWA3#2ed5*!#(Vq$AUqhZk-itbu$PdMFCWHK9^k*9R50HDV z$*=$GQNI}ZMHnA1^4+lB%8);d@$n)5I`*p)`8SaJk-r`FYmje6{{zUsi}rQMPeXr# z$TPSfH6nio;}Amr9QxUU{C4DF_xsm#wUh6 zjQ$KD|1-uRjy#Tj4kP~-+9!}lvE5PRt(cc2@=4U0Kt6_krjU z$m`J`Pb9zo@4)^RBYy?P-;4YV)G0%LIC3BILG-^8`P~=?Kk^~;rv~|l(LR8@8QZNx z{w>rABL6n>M&#ebc!rSQiS{kXKac$iBOk^1wO_!#6#ef)eizzDk$(d7(u;fw zbz;cx#JCM0KOOhGIPwEfe;E0(*xv;5yV1{4e`Az7j5BdHW=St+SMSuLr@4@)gAg@9{ z1IWLN_I1cdQ9p=0g?=_7e+~K>LjFtaZwvD8p?(u>T;vJl_o2=x^6w!}BEJ#qb^`e!sGmaqA?)uY z@^53mGRPCy?lki6BlmRX*Z(T?rx^J;*sd4({isuhya)aFA+N(asYLz{*lrE- zhcUkaq1 zRcJqnyd3?^Aiogpr;)z}^Ws+J})piu&!yQ>YU` zUW)ncLcRy)F^c?GsNakHbgZiw@~>mN1ITa3_{Witqx~@Q32Zlkd@1gCqsV`a_DSSR zP=5mXW$1qj`ED4WN#t!9pA7P5w4X-)F>Kd!eSZD_2K_8X{sHvIi~RGbQ-*whjDrvP zZ&AMzc?|2vkGuu_uR;Dt)DIxv2YDUxOVH0C@@C9?Bl6#&pCRP$K%Exk9q4};c{|#- zBmX7ZN02{`?RFtgA&(+I4*T1S{0X#=A>V?00C@}g8Atwmv>!(P4Emoy{sxTaDDp$l zK8gHYXg|Rm{YfEz2<<14{{j8XAm0sPDNUzy1$IKZ}tcjr*4u`7r92AwLOq ze8^A7b}NzBV88sxZ$bSU{X=pDoBgi8^8A z=c7OE$cxdR2=e7P&U7LF5Bd{D{%&ly7y0MV&lvJopw0mDJ5VQ%{8i}BF!Co+CxQGY z*soFKS0Ya$KN#aPf&AZSpF-Y=eoi7kAMG>9Z%6;9k&hwwd?>&ES7N;tBTt~c7x@tS zQ-=IcxIg-k-+_6lM7}@9(~o=x^=puygZ>1NS0S%M{uk5u5i zZ$9r-)a&j|7X^rs8?Ymi5g?}`2DMgAeoV+{E}vE2dW=b?Ta`5EZ{F!Hxy z-6oL#1>-P^d@=fyME*APe**cfSkEcs-#|Wz{7Gy#gZw|pr;#6raqx8I*Z*J9z8Lx6 zkb99&p#NpapGJKj^3P%%Dv`ex|Pg!(b$Z$g~`4>>R)(oV> z<|4UR4w+}(;Jl9*UN8|GtX-OPmq0b%3LeINlu!pn zPhKoX%{}rla>U#%A1jB=opOyFGIz+w$w70QTq_66t@1l$zqwgHUiO)r`sQzei4*tK}2qgtxm;c%N6n@3$#TS8BA+6M z%|&vZ95T^C>d?~{GzCiz0yYi^J)l0D{nd6}H~kIlavl2hhddAXc4SIfc$N_V!e3k4sH_PvredZ?lYT0XUkUt=M%=Pj$ za^~MQ|8hi5nQP?_%1Lvz+$kr_Rr0lR+*~1FC&$d?^7V4mTq@rnN6aPihvcxiNbZtD z=9z<>KP(5$Q*yT)FmIJ_l>O!{@<(K!d9!?z>@|%`IlpI%3LeoCMV6+a=)A~SIJ+Hx0jk$)nG%|-I495TJ$&^#rN$pQ0L`2pE)-Xi}@_L(=!56WKixcrdpF^|bVmorl~|8i1JnMdS@<)nE? z9+wm5LHQ9mZtjeC_f%z@5&>nR;HPst^6z`Rw~DOJ*b^A=gBkWKr{o8?!?Uh}xDkGRtw^O(H9ocWv0 zzwDJ$<`MZ-a?(5`m&ytApsZ7HrsL**S*L1C$IN~5fpXN`BkNL0>4>>o)+GYcVRNTk zCWp)&@VlI*2Du>NQa-|$H&%E0C zFga+RlJ!;0bilk-)>og?e)AUjZL-h2Sw2Gcn#biMWsiAGe!HA`(&k_G%PI4Syhu)( zhvaHGVIGu^lH=xn`Di(2?vr&%%yiV;BOfD2%-ym+DocmWopOyFGIz+w$w70Qte-Ze z1Ljs)9}%bh=4SbL*=KH&^;NL6*W4h#OZJ%S<#)@Ozu5fC0Xb!^mER*L&DHV=a>86C z>rxZxxVb{sSDDf=bGfXq9HgV>Qu$;#VlI(Sk;CR9xlRt5XAW>)DhJI|a=jcdZG*WYJR<8<#_6PaNN$i5=0RDf1WU)w z{qosz%-koRBS+0W^0{)v+%2Cchs~XGqZ~4K$oi-)9W=MeO>)58DqkS`&CRk-L6P>E zo8${+uem|KNcNcP>$23e;lPkYSu@-=ei z&o=*ZL{6D&#!=t$drDG*`?0a>86Ce?g9$E95WA zF>|^6B{^y?mA@=U%q8+y=9+U&-t@77ozj=%Nb=ha$EPq4x zn#bkaWsiAG{-&JygU!Djms92u`3^a09+HRTgn3Z@mK-*xV@(%OP`ze777lx5*=Nz}za|Bm2$G@^@vQxk{y`(%%~UjCk(`Mu4* zoRCxITKW5O(p)XyFDJ}Z@(<*=xkCP-95a{8Ka!*7Qu)Vn#9Si(L=KyaBz=|4jCoH_H#oUh}y8knAy!$v>AfTWtR2q?|I3$Pdd&^N>6) zC(MKLBXZo_FaJW0nfv5l%29KV{HPo;cgw$$!{$zTLJpZbrjzx+=*X6}=pmZRn#`CoFx+%5lG z4x2mWX*p!>kpCkG&293G95A=a&&Ymrv;1G#XKs?8mA&Q$`G2y^E+WnHQ-?J#J4ih`C#StsFLY%4KrM z+#w$%2hDA=PU({lm|Nx7$$oRQte@zmedZ?l4YJqVARjDy%=Pjc<;-K+{}W`NoHEzS zI;CSeX|9$lwC9=MXln$GVT5>^E@nBN@0K&avH6z+a>`sQzei4*tK}2qgthkHTrD@t33HXaLXMj&@|tv64OkOW%CT#xY zu$(fF$d}1U^N`#oC(MKL203o-mp95WbDz9Pj+%Sq%jJl*!pIb`mTuatx4 zHd#OYNC(WV@>R0m+$_Ie_L-aHt7WgbLH>a3G1tr2$eCZ+{L2wJWv-P!C@0O;a;Kay zSIO7PadU-yog6cl%h$_MbE$lT95I*3ACkl7BDqTrnP>KK{;(W0Ps!bKz`RwyQTCg+ z$RCk?=FRd=ve!H=e^mCE$K;R6nMZB@<*1x8kH{aFljb40M^2ar<(uWWxnKT-95eUH zx5!a*kNinFV(ykdC5O$Oa<3dRcgVNOL35kjCkM=}@~36Lxmo^<>@zpXpOwAl2KjTc z$6POeUe5f|=3kDk@r zxkw(6L*|)c=da2^^OQU&2h3aLugQM%7WwP4&%9awhU_(u%eTuO^O*ciIr9sfe>pCv z%p>w0a?(5`56KDhp!_X4Ztj=AEyv7#@||+j+#`QSj+ndUyX3IBQy!K><_`I8IcRQ^ zN92IHRlY~|o15kD%06?Ge6Q>^H^}$N9&^3?JvsA;&A*(GQ|4Ov`*PA;E#EIE%vJIa zo{|&hLHQqY+}tn!Q;wPY@nBN&&ipe+x*MA4dpT z-d&EHE95=on7LfmC0^1|bE&LLv85yC5?QC7NQccuvQFWe4w+~6bk?Q((n0f-Tp|a| zTjhOazj=$ipX@VlmUSwvwAVZ?zf$&?$7G#yAf0*0=3n;8Df5V|pX8;J<{?>^a8D=9 zgR)N9l#ZMGR2}V(yk-D~HXUa+w@5cgP3HL35j2E(gr5^6O;3 zxmkX_>@zpXZ;-v_2KivwW3HEVY29?@L7RVBmvT&}%(e2Hr(aUsJT>riySeR$U3D*I&3bIE9H=RW)J7X4n}1n9!AYmgBl03SX&#cR<%D@qK1z<8`{kqM zn7L10EJw{f@-cG6+$|p~hs~XGjT|y}$olD6I%sZ_Yvq8sRo1E4(|&Wae7x*4H_7_x zU)pPKkl!VH%=NM^S((l}VDm2r{}+pN^)Z<{nw6vPwtH-ST;I z*xV^M${}-ye7+nsx5-U%z}zZdAp6bDvQ9Og_L-aH3uUjlLDs1?(;joZyiCsg)aG9f z$tiQKte;4yljdrQIBUm}OiMY4WSmJXR` zikw%=LGzT{DhJG4)%SBVR5@%-!-8a@gD{x62`OhkT_RG`Gnea=_dwUnTp^ z&GP$YpSelCTK1Y7WSv?g?J?KO*T|Wl*!;^8Ic2VuKPV^7)pDntFjvXf%5igre4QLK zm&@17QFEz$gB&rJ$RCo!<|4UE4w+|mbN;X#G*8Lha=^S*zESp@x5yunedf*bO|sWK zE`L<^n8)Og$(bM9{L4`}Wgd|~E+@@Ha*v!a56U;oadW@?2{~r&lW&ou<{tTza>U#% ze@YIUJLO(EWbTk}m4oIsxlaz5Tjfv7esi<@8QEuUl0PeZ%?^7rMWxmvzoPME9YAINcYh5SP~W-gb1 zBuCAq@{i?+xkUbn95xrpqjJbR^V}is^}if6Psw9)z`Rv{K=zxr$Ul>P=FRehve!H= zKO}q1WAe}C%>6e1a#Bv2N92d)q@zpXkI7zhgZw+$W3HDUmowkD`Il32 z%3LcyAt%k%@)kK^u9AN*$ITV;ALN+1T>hgRHJ8eNk|X94`Ok9LTqIA*A@j`toYQj9 zJSA_H1Lm#rUu3^|i~OYQGjEpvDtpc2^50~Sc})JhoJrXH%NaRk9+97tljb3LN=}#u z<$uU=bHDsgIcDyYpO&NM9{FE##M~|aTMnB$w(JSA7j0rOV*aM^F(BI^_{X`gwstW$!dz2y)tRlzBv6Bqz;7a_Eh`5m&~+$Bz=pCB3G<+=Q>~=q=6?BXIcDyY&yl0%9{F53V(ymDlf&jtxls<8JLL1_pt((Mk^|;e zS(hA3`_0Yr`(&TFNxo3_nj7ScWRJOCUM6Smw)vMsa>`sQFPD?%YPnfXn5*O!a@<@Y zuaslva(R^;HJ8d4%Mo*le2E-37s)z-OgdzqnQ>k%2hCG*s~j+Il`ob3<}LCX*=OD? zua&*#ae1BWF^|dX<;<|nzZ{lR<`MZaIcXk}+vJ3KP~ITN&HeI5IcDyYH_1_Rk9@ft zF?Y*X$YFD*+%AXA9rBfO(A*|>$N_V!e3k4sH_PvredZ?lYT0XUkUt=M%=Pj$a^^0Z ze>ozj%(e0d<)pbO!{@<(K!d9!?z>@|`Kxl!JS7jx0rOV*YqH+p*om?xPo>Vx6h@ z&FIcn-X8||gB6}}VGF;YqenEpFuGvPkZ8B&XnaX@*@h~qU##`tnt=MNS-(PzBbCl5`;Kbx>^)H(W}KlaIUM`Ow6j>9mGUXtI6Kw-CU7hTMM2Nv#8hgX<+ zz1h*tb5U)=9zbr^Ql)CgO5p!Ive8y&^XRrS&_LTr{BP=1Hb1un6-O`P5jKO@J9ppTS$gFsf=qO-9nt&l1Apf!FYd+9S!Nx4US z+1Z&MenNaPJ6`h+kcxkj-W#~sia)dg04!$)FiN?f1u~?G@75Bh7M5NAJsxWpm!CcK z9AyGoFc2(g0*Xz9c>Ehc@YyLIhB1jIMixcmMQD2!OP^qUmL{U*ng>z`^gzfr8ei(} zwi2ZVa$SpoOqEB$!91|HDLVJQd-?C{A<_6T71B>VuQpkR?8PSAMK&+I$a7B?E-aL)@rvt!=Q`F~ z{vC0yT!(Zk>NS{pJbx;niON>Fla{bI>Ug#C`JpuHX&XI2YkIT}fw1Wth)a5aW(f2j z0Br|Jx@{(ej2gLFn*>=Y_awH-G@jS-SqE+Lw|J~wJn-z%i$sR~F^g9v!JH)Uz{rc( zHc|d$fGTZP1QMhWDYuQ1#bT%U;@7iA_ceATm4l{FhbI3vc#{^3EXqYafDcTTsy*OZpS_d^Vck*P=jT1&Y*`>sgR;-E{&d z$waJOkt#Guot=eLt0E0I9b>0zf?0&R&9? z8iR7y;(VRKfHr5r^X9F zy}&6_Q$#3ZQUIi$_>djOngdAD=EkO@qPwjk#b<-mtDO1qSd$|4f)u3OX<}evl1wBT zC6{i&hHB!q)a{vx*GmnAfyywT@i*Oe5rLQ#0I%&8uOvE3#a;v$odkEAPuV@1mMr>~ z@#XHVPYF(Q6{i)_WXk1zAApl&BGGI*N({K(;KcK%91Zp=!*ar40vk{uT&J=j z1wi;w`ZcuSV)Qsr&yebPY^>Jg&+zzae`(Tkf7dspR7WV~{zXe= zVA0h2*QK<`G*zvor6zf$CavTxRbVT~eBTxQs-&mfp_;Ta=dTKEXX0L3s#7)P?xaaO z^{W)PK_*Sg{ec$B>Y9}Mg(gK=0q3X!k2k=tXlac}KCelueRosfa#MQ0mR6W#LX*~h zeD#`g!<1g7rKKi0R+D1#fW`s^wpR5REmgCdau3y{7;OMgQ()^C6lpFO=2uPSDaCQ~IiwPBqCFG-(~M-4%GeDSbdo#j``p8(u}rPE1@;Bu`n+ z4i`|Cuv&f|?ka47xM2fm+29INE)wW-9q4yD`bU-2Ou1)yHw6#1wk zF9oP_DV+&YSuY*JVU&)9&R#NE>LthGCu_6|XR}huy)PQ z7zH}DiIh8NWvHwDG^x0xOuWG(?4~9Gwq#$S$-)iV(^qsJVCqbAl_cvW33JBW#DI&c zlnWy%=^-xgK6Uz>Qd>y-EsQDJlL8PjhE9%fK{`ytc;mW}_#QHG>Ln+{g|nU^Ov=4$ zF1S!+dW=_$MY~!Z@t+l;Zu)9c@kqJ5XwnjOgDg#Af&rSnOp`+dla#xbt_n=4Nq#8F zdP!oIGB+{c#0km)o<9w9pj-gz1y1GQD4knUfZj%n%fY!I9VTLB(vdK$8=FhiOHPOb zqyC8kRGupR1?IvyV5$v3|4HN_W;^PmNyQ}P7HiUyb?p*%6%!oL@FkkO$`I|YmeM;+ z@_k9xOA`LHkT~G*Ym^7WIgLV6FkS%a1x|S|Q0JBuptm!{b080-L#&ylBjLd>B9HZw z6XL;X|4<&>F8u{~FdlSh1Bef*nzJ48eOHt!Ch(UvY00|!WhoULfYk+>e8>>}>Bmw! z-z49aWW6MTmykGM&#RROQ6e4UL4yF)3!L)cFr8UafZi(Ug2_yf4zX01j)Vt4iA2^* zPKXB;jjWV%r$~PR9w78+8c4bQTLf|2(e9d5Oj2$yOm?_|gWkPcyJq$81o zFGV8jB`3s#VNWS;!#P~WIjCJ&U>0#pU@<|DHk5LE%OX8yJ1o$oVw7@!qE$-7EO}=w zkfh)O>`v0;7{Mv!zW$+xLeFcxcv&{1<#*`c`;T1>IF`Dv3skuCk5#3 zXu3PXi!lNktKg4DVOITeO{CqUOW%G3G%d|l)H^mYdc&|gJdvA z6JKg_lJuH#Pfkkd7?T_#$;ch-Y>~Jbky(6xPM#}gMH7(*&|hKcm$3=N?;=y9iOL2; z&Tm$+ZDgT=wW!o%9)hYTx@ilx zxcnDwW*Kaj&8skZF9q_(n7m!kjD;&RdG!IfAtvwZmwdP)lXpb`uGHk68OS@xPI%j>omvuPP`;714GYfRn=fjqnFel$lLv-BrJKjmt?w~-PUD4O04GY&` z;Iwu3hgx6@asg{;dGl#sfb(1IHT?z6+jg z+gV2Q z(q!)usM&1twh835n!F#e_O^7bGkK?K4@*sw_Nk4xh$@%bP4-KHnt8@ccp{KjWb*0* zd3%_=uf;&bknnOQ1>& zYs$Tfj>zQ2+(*Y@n4zPGo;!3*;Cw|1&cwJ;CxXA?qh|UiC74s2ypE*xnuZoM9hLOo zymUF!)v}xiJf8Oi9kLTy+u99Bua1^_$lv83K=UASKpT>Z!%$IiXC|ONVM}`8U@nY3 z&IFX$vmiLWQv_5yP``tq*WD>d$n%Shot>}9QK#$^BXZh6qLH`WAvJg;-!FbDC*Nm15aj!vSgzNtm~eOw zo*#|@%Ha8-n8X-D;piE%(2q2w4-4@97-p)#r(n?o1JKtmp+6GftRCm9z+{+#<9rRk zWQGyo2D5&;{qLy2Y^OZR1CT|Ms7*#WP^S=0CjwZUcbSLH2uM(#Y&-D#NqNjZN*q86 zCVHrd2AV32O@MNrUj#t++WRcR^I2&ku{7tz=>LEf_N>`4V|qxtpFS%f&6oxa(Zq;W zvqbz5qJx^4h9jDziQ)qUS|SIZJYq`F{ueLdS(cac0o-Wn-l=ir*{jt> z<0LeZ?x7jd7vpg@LpmHC$dF!#2QsAVnNVQ1>xcLZQjY&Cw^{}MNtk=it%}fT#!+&b zktgHgm2)vhbDi?iZwmKo!ejEA!lLr=-xQv?01v$?&+U=-P2stC-XE+dT%RD^I16`x z50{L;2aeP^L?zNJf}uL=50XXENDgz#$MP3aHVWgSPngeD$>GlF*YP*%TpJzkU{D>N zJl&}e+G+$sk;dWix7_1Jd@wgegQnaRre7+;Zye>N`#Y65*A;11%~dVp7-@mn;E(6t zL`Clm9oHEVIH$bt;KSKuIgL!Ke|VB47*lv5MotQ97mu=b#hx?c<=i-D zHcEV=*%k6rALWmuTL$3Ar!psb1VSB0L1T~k0wbV+sey6C!8FveId49~oR{a9VVU4| z6MPm8m035GH=^aqZs4%^nqhk8_6}N}_-GDeQ+QhLjX;66^1@8QfJoDc$mN{rQZX4# z#R|X~G7^t@_R)!vHVQ^5FJgy86!kjvoE~`>7aq9ah8>yO+oY=U#ez@4RN$b3sF{d~ z)OK_$oCXF@7-w_qA)&%)f%yW23%>D>P~&5{jsx z!ei(V1u5MD?o3Vf{Jg?CejE?DdOZB5aC_aSv15>OW9SGI3zP3mDZ+e9#v_mTwW6h{ zl^7^OrHuV2NV8R#uT>f>Q^3eFOp|!zey8$&XT&2=+wnJ%xm%JXYFyY!aEMI}UZHPs z-v@0+O^hFPE`d=XDHBeNI`vY;#J-&bi82KLK{U4pyKP+&^XsNaYenn}t?lvzlw1@o z3FEMXB{&3I+E-hWf>28bYD-dpmX^*4q1nhe7E2b^Q`9a3{$os!y_*PEFG=I~<3RSA zJwR^Cz3pif>gWKb0#)X1A)G)wjpE=h6q@Hr(zbdqW|BxdB&H?6t?P*u&WnLFZM;_! zMRxJ^CNOj`efCR+M^+Rp27Gz|_OFEHu7<5l|G_CQ=+@G8{b>R4^98(T*T4wIdTkFN z@Ti`FoV}#_wj1m1cBgWxGlDpe1+6OeD<4EdmA5-2CBf`y?ScXt*ro0QDVpj;fTb-e z(xS&~tw2$U7C9(NMfm-|yi|mrAeEWj8q6=2{h+=w%G;2N9{e^Rq-6HRF zMw)A@n|l;KNCm&7w)&m!g@5AL=;oK;f9_L{ajX_ORku4MrjeY;^r7)~bqKbnQx_jy z1KWYWNYgy(MM_Ky0y^l}JrWn94MCaA*v-<&~{S+opOxfyfT?&n(Q*93Z74htuH z8Cm4%2F~(xVGpgYV7dscoQu}BukTA(OJ>Ub8Y>=crYON8fDr-O?GccXQFz#%mQRguQi;}cr}uMu9zGI+oIJ(E2$0`?6SSH8qLs-;Yk=p7Ut zi6Va96YujdEadU3ya5I}TR2+?Q>MlsStY6@?irbQJTelXybTa58zhWay0?iI{^ z-dA#D!TS$kS3)EmWeOHcK~9n+{+gSld60Z1i668P6vgZ;;rCMV+;vzc$7v{i%+A4r zDHXd3!*S`k9spA20u zuIDPZt^r1D7gP(OC)EZ?wZKGZGIc6Y2kl7>J4v22Wrs;wV3OQz3U-r%oCC%8o4b&` zVifTkIOMpU-Vbxgef4oZgd3YZ3jt)_oN9cC%Z5+d`0-|w^?=E$VN(nt=$<#E@Km&x z#yWy|Wn?Y#hA?lK=2e)yzaVyCgG^&g-jA60>D|-ab^B&V)7QZdN%t1mqP>QkHqopa zGX)+KDK@V8EA!F&Zq+=->vG9$<-ZnY^(a=)wdU3!>e;| z%_cjFFH16>Ghha?qE7yR`?zYuc^Pz|VWD}frQ!`Iv{M_8SFep%xlUwlJkpN%Q#|rr z)QPm4j%}pLDL!L5+m@HZ0%h^4_6%s`cu1E5X%rVZl_k-5&pz?f`V=_T>)r35^%NnA zWSKS!=K$%-jwyI|kb#pxQAgpNBK87^feYb$`|W!`@k$q!@i&6_bQmx0vUsQ?7NjEW zpd2H-P~9C?h%f)<>1ezu`eSpnvnkL!;2rbspmc;ZP=F~maYHW_Clpkgo@L(rqXsL5 z_HI6vX}so$?wxX&6aJcK3P20z#+fhTQNybubV2-`;=w*ns0*n=ycHFMR~p#WQAK|FUp!F@ zwt3EykyLJgx{&-jQFRryE8u5Yvd6DY#LkNOsw}wc5`%l9j6S@AxPe)n4<859! zIGl2ioov#0o`@*7PheqP9kr!l+}Y6M>1##By)AjB{aUo2-XfGQ{mjJt%gC4h-p1?* z<)h!uyG@+ugJ|u~of9y4Dfa~$1>y(hV3dlyxQ{pU3}3r*7|rt>_zy$AJcp#}W)`Yc^&sB9RI#nT zKm-z3g~*=1LwX8f{McY~R9A3Kun-V-fFUmEz~$AY$erLkYPPcHVs>O&xgLfu4Py?= zrG*`h$WRNT{hR>^gVyET%Bx-6*T#HoY`P_0^$vn(P0{#>)`6QP9WYwgIx2-q{!adEBS~{>MRoc=F82 zuhs)4YXh1k=}B$|7SB!fD9gpSDY@&R^#dpPd^_KRvN8iqV}&WrRjUM4WzwQg`Na-X zDYCJ{#2-jwMG=!I)nA$bf5Yf>ZLpcVybleg4+u<`I5W(25s2&9r45u0o`Zynr*%n; zowK8mq9njakoUAb&Kr-0#A3m>2ato6gYb|A&^~ygv#^7ZpVlZNvLN5xb4rr5@+-80 zkvFZt#<3M-Xe*iZvOSW6V0zd@Zb-@$bfOs7i|9-SAT6!v5$+1zuQ0U+FGH!1BL*Xc zV|vS|lRrJtCohLIJH-#7!1$NBE~A~x*Xr6;!D+iFH(qPJ0HA0lf}6%(i>L=zdvQQ;LcQ-R^b6p%#IRi|52= z%*~1-!)@i`y~p@`4Ei@t@j55m68fnFuDQl=_q)0p!;t}9^TVB4P}$P_JCZDj7ys!t z4*_357%swms&0oJ1x1ne;0sB0FhD-2XjJx)(6vJl@~mvg#E6~QaWFc5m=6VR#jCi0 zqNA~e6ZtM~mNP0lMtg)g_`Od+F0Oq(H49rd4?eF%@I<=8bJBJ7*PHZA$4!h zXD?+I^|+_q#D*CRwuV^dz^yj9t=Hb;!S;Il?Uh(<$@X%zA^Hh%MHwwoFh^r2BU78R z)c7t>!^zLpPI3Mpy^+qv-)rIP<){Z%-2R}?-->J~wR%REh$T5&7By-ubY{eLmF!f0 zhdX9~EDT}1qNfglb(5ieu;7c!CTFWt(GzejPI=GxvVIHVO^J$bNVhs%`pkP#7y z^}lQLX>Su(qi6n}2v=+&w*r2Ep3lKA>~7Hb3zb;*7f_ZQ0rmJn1Sm;H0?oX|Caz{^ z#K(!O9~|kpDIdS-9;jfguZ4zrv%ZNCR1R*2dT`3O&By^drQuppr=}y|$5;(go6LYK zoKy3N561y3!R#U@@mIW4%o8lPJt55GI(#5WAFIA9(`8Io_-SEHInn`XJYAXuoa?~u zMeX9qe>8FMK?frBaB6N2SRv+O=ol)cpT-E_~CVMZ*h8Y%)=(QimK$5&1 zxpU(fs0=Sht_C@#)ZjD_jU8_qdyfl1uq0L9m%ge#?$5_8zP^B1bC88X%3~Rs!q+<` zD&4}7+!@wB$X9X<17ZZqBQ+j8LTgv~X>OpC;GNK2o{X zQz>d>?=AGQ@Y^5<3Lu8&U4wQVO_ycEo*)e0$j~t&%2fi}Z4&I~N1-k*0M z8HJk9OY5*3wRpL`3L$dfny3JG0jdFnzEBS7A;@UPU|=1?V<^ka+snBBi#_|5noXr| zW6~XxDff6rvXuuEfyslE#?t$ljRP&2B4BfT5wJPF2+Z}z8jmv8iZb|xwR)TEH%QE2 zDN#6#a}{eIa}ZO|Y6P71H$f8aze0vt7%`B>F_SU+qX(#&Wdy!DBU5B%w6?(V)icmo z?c%77L>P}1qXo@RI}Moa^qd6j2}hNyBe5xGz==iJ5daUM5o`Z^ja8WDgM{w;6#GFWkoxmn+R-z(awEHq^iKnHjd4Up64Cr z9uR$)5*x>M7_o>J=x?40PSufK!?q5rz(U=Bfeh3A+Q;zdhsA>7OdWS&{63rz608+5 z=*{GyMODYz9=1RRLybmEE`g(G%>xh}g`|IZ#~RGvSh8wMIq73p+BT4wy^3Xh;FwGE zqv!zyVl59;79CxBs=QDxgM5FGt1adGw-jZca7a4@$B*MYGO5cx@0B^DeAhlxm!K`f zY>CGP`#e$fm8j)O;XcD7YOL04qGVLw=i@nq|I;i~{0|McrDw%z*Ny@a(=lbILQ&xl z$0QWRXQgJOL3US%zDQG}r8p0TB_JY0jb=YjZeVOM)t>r2cSEZNLscOw<$ef$pAdi9 zR(%>;f9Q*{59o}T3ZVJJ<7;~;ijy$cSk% z_3)T4Q~kp|crqN0sANd@>D5-cJ$UY_g=e3x9onN#5h(320&)9|f+a#$#=`{*#6Ca= z9QUFs%E~8RWrIT{;=5ErZVW z_<~LmzaZlXMDoMjm6HD`idc%VQfz@iolFIsO7cR4$K0k&2*#_o6TO{s?}0awiJ3*+ zV&==Hk?UpRPj+Enrp2T;nE-t;8A9UOo3lgJ)a_K38}abhW7*J!Zhv?>Tj`?z({Awl zZ@D(3{}eJz|J(ZgQ(#GCU*RLAR@Srd5QSioq+a9MtSoaunq=Kpm(hAZKg##CwXz!N zV-NGGTHTj1LCuJ>%Yo>!2?CKs+ey_}()O>>HhOP@OqXi5?0_9l<{I^M^7_L(Oyb3KF8`d^V*x?;ECO3cc!*EB2N*oGM*|C!e5E-yN0Z?M%Z38R;=dLA5UDy-W=&JuDhopR@k zyDVos0fqC>H>2ypk(R={aM-o5E~!qWfc6oehpSLYzDs9@l33M(EL47<_3sdi!eu$L zu%2TSk5EV|q4>=+*7Oi6aVg>X90P>HWzl{Mcrs`~M^7)iKwA|4+{dn^9^6XtK%`MB z^#!YY@+7bHUQyK64UVfOaDOXvSOaEr?u1y3h^oovAh|{^en%Z{7*h=6 z6;eb!Y0cD%{6u3PSos>7JlrzrQ7=}Vp$A~BEj=09{}5O(Px}kExiUzf0F+ue*^jw^ z7%1M_SnK(Mu$1-`r%Jr#RwY7gLgFj|0ejI10)Bb&@FhfZ%>}3tg~P3zT)L-6mhLfg2SX^6-J6(; zHLPf6_~-BxGNeRi9s9|u8V^;SDOIz_0c^%rQ(v%L6r>IqnIAYIk{KRBdK;;rYfulP zB2U8@jd2guinc6kOL+w6CynxC$%|*{=wsM9`j|)N2lpEZu&m-e9URisUt`gTIsr`` z9>?%9>D#L)03=oxROm^>dwqq+S*s<5BZ9X-T1ugzuE`tm@QmnE9~wshGE@MBtv>8V zjEp{v!6gdG>jZy|(8f)N|56`TcdZXs!-nVxhN-|fUBby?Fq;XR6~gR3ak^wCosxlB zhHh*3{OxcL{~@2^v^V@B`LkP@qq}5ZQp4vX`Y-!5G!L`~B^&nJD>ce?U{sh>gcToUZYk9jMK2);O)F5J0bF=u)F;PDW@V*BtF)2Epbm__;@P?w~(?GLZj8 z3uocDK@L}Jj>h6JC@J^vnX2brU-ev>5C$eqcC&o3p>XMPlePSWu1X$&IOMLg zNZhw+0Rk8P=|MB&eH?eO1=d+O7Vt9w-vIdO7@!%5EEnjnEY=I_9@4ci z3g9y&DqwF3B#U=c6qn{<6-5g|LyRJ62W^6{*m+^?IJf6nyS!j{VytNi`H4~38_;c- zIbuNa{FU6JoI|E?EAgn%7;QavtI0C;)M;kqh;Zbt29wBq6ynjGd}meT*sEZzQs6afrKWFZ2`Q zw{1|y?3U9pk$$6?;k<%F3k4 z)J|*;e_&gdqdZ<&XngEj5JdA-Pbu0mH6hvARR@Hs9-mpYol8rZyKx>RmH7(-=-mqe zho9>86<8tWUNhLUS@fZzKnonL0wWl0$Gs2au!x}WbOTmazM!Yvui)e9J`jkhA~b5@ z`x8d}r;mVKyC={>>logQAP@mAuE4KtnnR*!ufkf;JrU6W@ICV!Mu(@aYOCAxCYV!- zMssQP3bg8L>r~;c=M@+_d}%Jp$}yBvjyV`DGWHyIL<-3L-$?+5`wHuH5QP5z$6-w5 z)VzoQ<0YEJ_j@MFa5amh>X?6dthLVOp#4hGq38?eQK+i|>we&xh2wvY^)^&dVjY55 z$2jqPtmn|=8H{cKil8ru^>S}jV_;4vj84gPEgpTW{go6&*{q7rfI10?abNNXD+-+s zknCmAID)gd&yE&8?4Nk@N7+z~7mjlFrv(nIvOOtfs3t7a^hGAGZJ_ClzjR$Ek>EN5 zKj!6fef8UkX&KIk(NrK9%DZt2>;8?3a{MFeLmWK<5QtNpt%pC%Tk46(LuQVT2B~6R zy*5`sE=Ap^+{Sa*H})B%P@ECbzD+feEZ)(W12B-5gQ>JH*Ey zmHQX$i}Om9$ZYR&={VjTjVGY@$h{H@*r!NFRVexa?iE>hx$GF|l>u?wwrF0q_xbrt4e^i&v|LCO2~hm8l$8W> zmP$^U#ltpZ#c3+YX=@PA%_2JAAo}tcrNG>8eGg|LZ7}ZN5!&pa_#_-EBuuyfvNn}) z&rt5=-60H2AILJO$vG5T6N_CH3t^z6LKlK&iyy)#i11%*YP);)RuXAb0p)-S!a`$71*pot^;A5}|=9pE4#;hiL%(kMz4UAb(O253G zWnD?>x|2aMUf<7)%BAA?z8u8XjKke$60LxYtuhpBEfi!A&|O!^tQj33t&pBWV2sRV z5IKkG0^pLq7UKvCtMC^D;^-X9avb5#F*Hp_5!J4Trqv%BYOvNcZ&I;yX*WEi53F0k zJ|4Q64W-;a<2NnRm@qjpFXu+)OkPYamf=}uMJltbhqdiqyppj#-0vt37SF<bK- z%z+2sU&X+f64R4sGZbGh_%xzDc!$;@pfOO-g9=7gGkpQE)0cAhA}*^np1MURDfiuB z%!9NtJ|FqQuyGHrD&@szW{H2WdlXp$f&1^_iGeOReLSn0%x##7<8(VB&pnwQgxc9! z>U;EbSwt$)tH$67fBIetxA#=`<=bH|er^1$x)VHVGnemO`dKxb<7f2;K6W=L7++Nh z8OU+N5)js#>qI<4toYDLO3-E?2+<`KfA@EDEPgW9 z7-!*)u<%{1+btEoycV9CA+I^To2?*#Xo|8>z!7?%-i|EliZ34NHDGd1lbpM1sPuG6 z3zfitfE+|%8zpRGHq5VS6J+B1R8Vdv-IwWlzr2j;h+jUC=_*scq`Vw+GU6^NKgRqX zYkr5xFZzoL{19kjxp0<3EVM{F)$qvtbKvHchQ1Vb1rlUNWdI4rJ$xXc=+F!xVby`u zoNNgwcmFM(Ro4GZs}c4C0R<^39^o@oXL-&Md0bb&;B4{mitq^N;YaXWj(nYqSrH1B z9pJm;J7gfyweXan72>DbBqv6nab>716T)YUp#$Mg@$;vIF?5P&NX{l@+$QerAL&h6?=$6goF++i_D}~d1wN4r z*BY18n2W8JyPupdr?qf699FdcI+SXIqKoyE^qGxi8K$*01|0F3PT|+p+eCh83NXQbOIhXF3oRoOjQfcIw{EHc3tMe zn)tFjC8sR!L|Hy@KuDH%%8=z3;1*d)0Al-d39O3+bOVuBm!lrj8)pr3OYgwLHzmFI zkN~IGRVRAV`wk=!&5O9s6$gtRktDYQ!e&G~>HSRN?&gBAao2>Tm$dsKv5^08AiOW* z^KG^lwC12d9c?Y!f0!*B9yxb^epXXVEp&uGIXo_%0w3)3EOJ+r!+GG?P){lsZtT0J0FS1l4RY9U(mM>f{g1ESSv6B*#oqUuk9 zt`?3!Q!vRPs;=<6+QIKC=eRCBOzPwA9P$m~45O1OF9KSZkacWdhq+fdY8sahSZxp$ z<^`B1QCS7n6rN{nPw#Q4p?$rWf0LE2&-SMO7#P zEJ8&@)My_-2UKs%@n&;)oF#~F1Nmsn$j@OI8m~rI^0Q8a%!`4`4oI$8zv{wvl!G>I z81PT->O!7)INw8wZB!Cd?hcqwA&iJC>f<~eLeN^GyTRpu-RlJ!}h*9PlQT=(G*Q(XIVy~6@qqtoY*I0z&xHW~TOB|1aFTc4smWsL#o%7J1 zb=n7T{K1nip_BYT@W7+KEF^C65zXmSfuTs*{7#~BkJ_L2h&sBu?f^N0OYQ# zR!Ex@3TcXsH1QMA1Vr#W@WW_}fh&lj%#8OcgeN$5%)F{%`Kok?1G0CN^a&FQT*qWcDf5$Y)Tb&ttwd3pmoP<=az z?(9l(UnI=C{VE0X$|aFm8$o*~MY|Dh%PioGUv3+TUf)F!X3}8Gm&^s#^kGXP9|70O zkD`f08A*^OkktAFDgz^x^lLSlTELl9JB$h9w#D?e>AZA7dJFttE^tn{(Th=a@?wge zT^HFoiEyK*b&5P)1lt0^8cMN~C`os8Y<0M;>6CX}^GBMFteR@^Ft!wKt|i+I@5c=n z(t_G1tPyRWVJ)LD77Gg##H&>Fs1fgxq8);}97(8>fQDmxIINVRwX*um;Fs0#U|1uD z%x}+wBNhQWuXgBDzi(@$(7(8b-r=(Gz5|fuEwGg(^SRn^`*FDp?|*Bs9Gu1GOVQ?H zac(vipvU(G-aH6RgR*@vpXdwFhIBw5XZQl3Z{yVdfN+7q$x<8Y=ZC2FGjGUd_v1?| z@LQsX0Knyx`+F>gGWsIYC>f8%T@KEKTDmFFQUgpv?v`#vDAaGs_u(i(VjqQ1vO`k= zv!1;o5LuI>i>OfmXbh)J^UDzhmzzB@ylr0or_Ld4leVsYAge8hJ#cyRwd<~gFl68? z5(=z@3!?0fI23Fa6pDKe4uz7UdM*>}668=x_9d8xPzfCw3ncNVVKJoP2M?BpTVWwf z(1F>`kfLWqn{etEPahcUlR39)&Omfi5{kzsM2)s^^lstOJg~ybz=H-6FZHS)eka53VT5SpEy^>w{q5vW8$_H8)^W0yc-<_yBP)p4^X0T7%;zz|{0pS0 zW(qUo-P6CeuD^5!e?b<&g7_;iO$Kp#Q@-~z1Fg*rYY6qBoC2v*KbLZU(Xt1Kc;eZ110 znXj8hifG_ID#{#mQ&bSl)J?vW(2tpL3^??P@Cx6v6pxQfOvpmY{pX2j2ftfOwrtie z1>bSi4sVBtH1L(N0{_Atdnbvv)0#ccmQsD{JUdDy30&Qrd35V;<-m;&ZEaPhx4c)G>EDk&K-Dm-DF12;>&05{b|}x`xYNC;zAcx#rP6 zk}LD5;Q6x9JlaNza?K-jmU4He->ryGrk(R+ z3-9J*Er8jOwDW_zk0!``n)vtmdy|22&ZAEb^X5?pRD{kW)J(bk0P4-7o8Wz$dGs;- zI!^E$B6sVdY%JwIO(p2Z2!ddu(STd-6N;2{>>c7l8h{z#9*DBG3T@ga_w9#Qvjhw(+~kVym!$6rgFr>0Dn&`}*AUo*SS2f9K(o z8&0&S;-1_+2k@$ZbsJ$_w_@-J?;qg9=!4+(5?&j$A|Uca<+Sv*DfbrUv%Aq zuA9LF{HENO#9q@n;Lq$__M;}mB6XR zWueEjE@cREiu?CCa&%0L9vb*7b}o9TM>Me$KY<43*;7%d@ErKy3n)M_xwEyh_yq9B zf{Mf+4>VH*yOr5YC_2fBY+5<3%T{&;ueBB5>`>Y<;8=7XP1cjhzad_vA;>)>D&S>VLyQdSy|xc3nx^RK%yUsS>e(jZYLz(x@mTd+9 z;ZE-pdfd>`hK(;s3rIg357{#q^bUt3Vf$;AIcVypm$72{HL11Hnb!~1x|n(AiZqL3 zxfh_&(Z=S6d^1O+X;gs|c?Z~igtZ>#7M^w*#wQ9WWe%U|%)5SnNkH=O4uQ#E5?ObE zmy54Qs7;!J87d+i6wZ+K57TFEvRyFJU~JCV{==q$&S!9I@SRaJZwnT(jmf$qg^v%&e)9qRd&d zW+!iE1ZPbd*?jVDURh|?yoc@4R~BW=nu4xp%{~%f)}gyESXX9EftfY*6Ftj}{(a@& zg^PU^ggiqE%s4#?wQuzdC3i07GyfH8`(g%+1!%^S0Sa07t*fbMMM|O9Q|^_bcTueN zYSkVn^^J*9*zM|{;e5DE+3=@jyuxo0n}FK)&<)XNO_%Rg$gAU&!Rn5@3BOjkF)td+ z8?8V|Jo?)?WrS$^8gfgtTeIoK=coS^m<8eJ^*^__%=BkBZErYiuu^@YT#=3iC<+BJ z+C>KeQ=D(60Ql3{-rh?Kk8=3u`1IFs=c4A}@z3>$OiwzI7zljVb3f1ri!LFuH{jl< zcfk!{0OZvfS3rdfkHeVjc?KCAy~;LYwq(ZYPs30umo`T2S2|~NQG3CV3~Iak)cz4m z_RXcXgyD~!X;reR-2>AvNbMvjMMG^L?V>NvP4MDgrIwNoSqQkkbN{aYwhrV`T3`ig zTQ}HxRwnG4OI<}hVSr}`OE;c_p=rg}CirQPP=Eh(YsPUXr2_DmGxW>YbEIQ>uOXv;Z-!dM|O z)OSbqD)#gi<`#9K7W;u%O%1JG->onwRZ&H?2?O$9dz??Yf=XEfFR zVM4%BK=_WL@2%MIOvsTs2;FyZS)@0%bZBIGLG;J>Q2@sYCvTug>1r%>4;dn?Ffa?F zKYpMv#<}vt=dH$pp%W?0ZUPhapdmC(${j@I>id-YA?b(D4Ly3$Fl1GY#m)-qsu%qo zv|=zuHBBW(W97MGR6FkNd&FI|Sx#Rv5cewg+hpA9WlYUH-$Mmu^ZR&KxOQ!MXdG|| zZaCB_9CvSl2@S(INz!#;cX5{J4B;323$Ng+t+>@8N<%INbeH5E02K+bAJNQ_F`u#* z$M@KwGCVj>TG0b#7=$AI!bVkAvn~{A&i*{%1Zj2C*&GC{&_SC%T*oXeEDI-BJ5t4#>R!ZSWk%Mrxdny;ZHT?Pk`P2HU4K zJ^&-VRf+V086rC(__fCr20(gbWHt$T83uQgK>NTG3p6KRN+j(a7Z)CwEW9r%-#4f4 z5G<)k;++cRsh^Eny$as$o_BHKX$w#}e_K2k-jhUpCC4|?#iJ?Svm~fNK_tH4iREIh zVAxmCeI7AIo>zn#pQ@si+D*BkoZ{oNd%CHMp6YV9fu2sJ^CD_1<(}(7`5IhZ#+`Zx ziJ~(o0(1opkm$6O+b!I6Uz@)b8V#-6THx;(b^Fo~JozovIP8UW{H~nk%C}g}nro^w*lh6GjZ-b)N{fM70!0$c6wJPc`3+_Y zdiQ5Q3XZ7^NI`UAo{#7~-SMohdVl&FIwA--7PL7Vx`%Kp!YK@Yp}ZDxOWDmAX*wg^gE80j!>M_ zXLClV5eo)8LUp@se1u-#F>{2TmzNKjDLB?{&Z*xZIKv+{dLaTQPk5EV#I>pBp2M4Hws;3N_mOg9zJ%{PiQfRlt z%+r$NtLw;(L4kk2jl5m-W<3<2qSy_E`Qn`lf^lP%eeXhK0*kke#|-ee%+{EIm-p zb&*X%L{jcla9TGO_w-8!vgB4Yq$ODqtlvunOWR3|8W?4)!$Ig3p8-v2thFDSMfOyE z@x1s7$(A+PQfdoctB@Em)xU`9UQQZwVUoQ4QGB#t<$hZQST*l&8piWteQqGObNTF% zR?4i|sFp>VScsXhwmC_gaItMeKO2<^X--Gw+O7*t#XJIh0bfBIXl63%!-Jj3I6{H> z_##0K-QGnTs&VYD32b-aobqGwuBBd5Y8EQpx9(~Lw-hT1!vlf9hG0N{NlV9I$^)bt zA4g_j-!#rF{4=%e&W+jeLI34}XoFT7ra9Dum??pCa7Osf!%9iJV!MOU6%NBxl0A!*XIDbC;%ifa2hgl*q5VCcF?}`3)GcSDe*Hr`_j`?%p+BQq+38ENVS=AU99sh zhC=mnF8p;VD)(LdSN7$vu)n!SFk~tI-`SULKyc&srI0>(*uETvQz+n@uxb4Fx$MhX z$TiH{gPzL9?aPZ;gTp9b=M7v>8}1$QUDp=oJuG`d7A7CShN-V|Nu>9y1TD<5J^vdE(+eJe zu`mnsHf>?vL=-JcUx|fT4DFJWH5;=q^KoQ_6Yvr=3${!(E0~#*E#{(^mSk9%<>CSB z+}0J$jeeC67&0;b?sk+eV_~}Ma|1j4L829QaaPK#Z&59aG_f#k2X#SOE(`Phzm%kD zibbPY!K{{SA?Zjd$+R$seI{5p5|vTJ&b&u8T%L1Sm~R>R@hwarz~!O5;HB#Q2@`hFnyU9 zv@pGM0QCp}i41&02QYgDv%+KtEldh|wu2-`XpW!ZS(v|?iXa&8L(qlsEzGSxyi#4I zzy$r7KE!`zVaj2FbI!T&TIBzog?VVb=ul(ta;;#V5_1yLksn}P2I+4lZ?;>P%ffVg zfmxl-mQ_9(=Ajrx}1=O%<50r%m1{HDa5vr;XYS+Iae|_ zLbGSunM<(f$~~~T?98QDE@fEhd$4r0Jbd-buIaAL0L z^R25k1nhYU(yj@8rLnlag6JC7G}DPs>G#GD3o7y_u zg4LyKy&-v%HryA3T$4&X`g_FNmr#R<&m0;b2|uLVHM0MpLMR_70)$}mafeV3$&u46 z$QFBj7KPTSWE{XkZi!`^l~if}F$sFeV}GJ3YQ(z&FLQ>B>ubGFlz>EpH>7RsXF%ei z40iC&DB{9gh91&;VGQo64J$GLE2Ws02_3L zQ9EEsFXV*3zxo%b{PfmoP?~aAp^CL$foL91*3MW#odI-Yg@_S@SRfedMt;4asv7m^}Oq(22o8pF^qescOyW2jVzr z7!k2VJ^Xz3ULm~;J}0<>fac)72W`1owvqPn< zeeZK;*`|b}J3_h2vN;1V>q4e&VsHjAFh11f_0&n#)8EsXG>H z-+(YpkoAh!%cDDVC3PnOuq&xM#rov#Y)EaE)HRC-2E~?3>fTlatkg~8B=qN2G4S!E zZaOvo-tbBjZyXmHI z9Y-7cPZEvs-f?cCLPmC}WXs#3pJASD^imM14Q{L(njXjZuh-2y$AN94@rpeh)a|Ytbc#(B-#Ct!OdS1oq zIQlz*-F=@|>QTZE!3#{e?~X#lg2WEnlCY5EEaj|q^4rPgEVuas$rZP`==p(EoTNbR zj+!q;)@=^n9fi(PZeQO=Nl=UW4y2wOr~n6NptTtUUh)2h&iUnN-d!No7$t55o+uQw z|MDTYAY09H)M2gY9o^_`_<(H9U-lKH1d}FzmdK01^@J9oMK+t%RRHzwyqSWLGAB&F zgdPkpove!v)W(Y0p%X3B?{|_k-}cHNYVz9g+|7=^G-U&vjP@z9I{X5o@4wtDPhOR& zIvc4kkRr`nVmR%F+_C19Z28^WweSYcawq=<1N(wl`{F)4A?oCRXee~@(?WI1eT`f3 zPK^Ds>H9xLvbLieUZv;zICpT|5;26Hr1VOV8%@+pG9exm4gt)4th-?KF_ljuHpIXl zqp*@Rias&mb^|+GVD-*R&st0c4nxHyocC+?3v_P$^7aOnL6odLIXM>sgE@HO)>ms&2F-$ z5lwn)8m!uEP1<4u22OD?dF-t_T6K@Y)sGEf{IcHkJNiBFi1SreiUjpCF6rGs#-77S8h_;uDMkpclkjTJ2yfWC=5GSRTwo z#uJz^SRM60&vqzO6f}D9n@1w{`O7 zi5av$bn3#^uA5ll{9D?HSZ0vua>*Sz)*$yh)tKNd2Jd7kt>H3{mnD{3VK6=7{aZ|P zGp6^EM`4pUd2O@Q)GL$i;u7oaw_y8{C~{wx`aC97Mh)Q9_Z3AT7VutG4N|}Z8>`$u zqMikXK$S4*t+oVpa*(od^zy&D*RmW z>K(>w#!re@o{!hd2uS@Wc=?{9IZ=d#KuP#S5l`pjK2hX-arYp)$+9c44zdXCD&yG( zDgcbih8g;iC5S-ph82m80EuCH)mPQheqgone+TO`sg$y?J~l6e z^>-2lQLGC@eTJ~U=#31lKV?);mEQGqL<3lN?TgQcsDc%^utaxWEu^~VUw_7l?8l^> z;#Hb6kghcALB+#3rQ9>1mnDto6^cD&7vCC5pTb-XP}14&Z$JwIRr{6QE*Qx>|hq>tdA zabrnQ*Eg07V^EkZMVl^6k$2mP+*neSbuB4pedd!Ul`%=ebLv|C`MLO zlhSsaBu@gGM8r63J01kIXFG->er;^WWAF#fJ`rrAzZvu(g3DCn&~H%ZxIYIiT5Udg zt+*}bOV$Xy^W>y^(`y^-m+G*WkM9(O@1FmV&bjxwxv55@?h8FDD}<_Du`0M7z1fln zfI#k@y?%g7!cUp`5h!L5dIRYD<^V$dUsWbNfI&W6%u8>-Ss3x zmXjBgl(RP(TNt8KpbLF=uZoe8dOBx+)Eq1IGXKn!!F|$n8O)4af}zNz)P9Sl3AEJY zb#%Derog8#ql8ZMZWI#KLV`?7+Xic-mxaKy9m(H%1cd;d{9m<#omrY~OUcceC`P%p zaR?H2qF97xLS6&Pjc1iQqMqON5-db6^%gdr!o^+rs_KFBaCH_c$8 zuX25hK~VG7@FjG1Ox6DX&S+~_WSF)d3bz$r%_+_6mwGf19%jEF)ozI82k--Or zY$r*JX^`TK6kFacRDv^k7pOBH{(8<9v-*AyOAafdnS0ktdU1f<8&Ptu!rU zlT%ztN%DL%<{Yaz1GB=MC%*0RZw$_Fj=be;Twkb&6i-s6}KaPA24_C%;FFH!_e|b4F6Q*s94lR+2+akY?CPb?Wvd(U zve6wykCZ*74gwnYX6g-Ct-#Oxw~TG(O#LjkJebLv%9IC8*4&GUm!YxK2h(XYYWqTH zQ-8*K_*JVfM^snS8U?5dyya-_PLtsnj6ka>Ub#;l<0U?0{bCZO19mAy#lCM-SeGOx z3=(&caXwCY5M=t-rrvokvQ)0z@jw5y7B(*$H-nG&|JR3F(D4;cf6Mi`4|o`ZMt)bt zA_xMwhDufdTcZv?07jv!=$qax0DdjqY#r>^(Bo9_rAUIoV#~YW%){0sg*fA=SrXpO zqFON+>JVE8jQ14UmdjtHhAuKLLBC}JbMAF&yBA}6c%A?;hK|G4f^ojnsD4UMueFWomyez!mxKCc zCFYsrIK>~olc`^pYEDl5vLh?1$c=)Z5}b+I7$WuCo(eA_re zwd7{4K#YDFBc%a*)1`j72s>9H{jwPDa1QK0CffPR6jl!5ata$6STeRvCB zesJPo(88*%#d^1O$EtWqTy|UppZ*(DgXfdvphZ>1!XRXn54?vGhiEOB;?#!ETxO)c_ z*pDsP`>(0qkT;$o$0Oeb>U@{0j;(=f{x;~% zOywO`YAF$Y?L>pv0!#i;lgT>b9u4@pDers6xHr1Ih};vXRC!6@xis+H*L#NMn1sko z$OyhES`|!9xzF%15XH3X=}=U7pf|v{&ov{kyO5$A2g*d7=N)ln9C^e@GnC{6-V@f$ zp0?t2pk0vJiO$91ye-zk_zc#J%FCZpX_%OrNORj{5R}n#RC|W{Cp;&Pc)Un&1dCdV zuVBG?7K;%c7Hp*iCHVERm?tYdkWpLRY%f2&ii>g3oIVs<*xeri7BfN4`+<)s_XN?% zmRK3jIk1B6!EGq_KXfcwi{38$^b8GZeBkm0R$e>@+?4G6j4j!eB(0UbmB{}pNfGW0 z$}6lQq$zh8)`5oZOSuI2UnHqR24OQK>7i%YX{IFoBHY3J>M88DV3IBTjR}BphPKt_6v2;t72=_e-wfAyaJVHJ+sKr9S)XU$7!Rt!A9ft zU7?OUQ#7wVqwG0IFd`Y3R~sgwHd=q zy4G$O(U!g#(egVCMrJ&ognO#7!Y#m^yz~VqW>_z((p0sjNKE<+SY>b(_M-FE=%D6n zdTfZS$zXJMY%R+bziqydimVQn1`F@z0j1b2I2lyKFWdE!FCu4MhugrBd=8$9T!< z4Jd5e1|yb9&s=;$?Y|hOXHgB~^enIV^#(E5I6W)l)M&=(*};*y7^ijr&~akj>~TVs z%yBZ@8)4xwNR1mCB%gDEF~D_>PirCQqU)UcihYzUlHy3-^ zT*%=@PF~x>c^!Xg6z5@lc7^&>GIG zLhvKKqokb5q|pFBa~W>{4#dQR(w+-VJXgQ84XBj+cnbAo4ThVyp96)G+YJ$-DUmt& zh6+{i+-N6UT72|7HVOEaEs4y=8s^#lOCrximPGz}5%w=gjx2KIeRD}hokWz>Ip%!_ zv5hCda)^$j^=WI_f;L4OB`W(r!NtUrw#HyNX@uiDd8$pAOK94Ebegq}XkOGP+Vd3a^0nZHXSOY!$+UfT*-LSAuR zSoaHyY3RBoy>DlAYX+wp0$pBIShrYhvc)@6SohCxj@oit?%DFW`Rr+FUKNxK+KlVo zuNW`fcm6s$DIy&(H~G$u@S!W0?PA%BV#jkGGsPy|I# zZN?NQO@~gW2-@a-p0(EbxHn0enfLv@ewusE-p^ipt+m%)`}6Fb(vEYl!kRrI zzS+JBb{WWgT=cmDQ1B(X9AB3OZ_$jhXDOf5r!mDvUquRz$wOuH`!_3BORITY^v%M7 zK((dZv@3rih5V^YnUTz_+2Ha7+W-%RqkJ=8gQI_=pNQfzN>2}%MU&3TmQi*b!qoC_ z1(^`|mwv=0q)(`jqdKc+zZG#I!t%Edri1kS-i!r?m ziFR>zEFsa~k`hf--qzA~Lc2Lvp~vn-Q<-{~zAriBQ86XkQ!9 zo{v`4>o}DN`b}^neZ6a zCv`KCA&l>l71P|i05nG52or&0Lx@)=6B#Nr$2LDP-yd^q*8<)YZARfnIxY+Gd&KOY zhu%itwg=`BLY-#Z-B4tF9tsMHkuo{pRSxwJDd_3{hwU-5Ph`!qHGlhf z=@b}!anagH!ESkRJ(2?L$U=+@JNkY6S4MvFP!9fbA)CJtl`R#vB~sne26JAyY?NX6 z>sHE$r|^K@5q+^j0E0`ezt$s6^LlcqIXK@RP9V>k^IxM?MX&BqPFY*4%9*zl4zfymAi4zMvL$WyA~EcrdBu!}|mdKzH@yBD5CK z78wp=b}+y7<7-=Vu5Thn4?d+SpoAe^A(~0fP>pZEQTlb`V&iL_{6S7Mt2}>EIX))g zu#b(I&75wPI+}DXb%C3A`Az(&S$Jw2pdf`Cbxj<N!LIR= zqd3b&h5eaSo@)v$+rxo^Yqr7JUhW>4aOPIoYC!Ridg;?~xVr@t&OtDz7vt1K?2aJb*dp3^Z zfm^<|90Tr)W6>>m#HQ|!7aZ6_Y^xt@hj+CEf-vOh@*kr}kcs zIb!TR#7q>5b{K{F(NlXR+Y1(X*+N{|xkdwY^^u?${cfjYwS?I)o>LB6v3kbHR@um3dpivE%;-(R?{=A=!0-jnZM zc@p{7q9HN)3Q(C$z7J91wkKZ>%WoA5poj8<|Nlwl_bBR;Uw+e&;g8EF**^4ym#tTR z4weQW-^%Aa`JM>m>q2kONVQjYsn)^kL8{BC z#%@xbA)&oVb)>}p6se9to0TBdn@{#A)fbQZQjKF*XuDF`p0Hm&N&yl|Y9nVdoV49~ zEU6!)EPC7%)~3Z&4m;PQ@YNTWlNHK!Lw(1u#An$%elZE9dp)q# zL*GV_ZfpX7m`yfcv6comE!p(-vWZU^Wl^In%B3xG^)5)#|zFZpcv+3E6A zISoIt_+|JzE><=fKb&c_1A9uAGCXqIj_6Q+)joJf4qVq!!1hxyR(GQ7FbU<|*oAq1 zV9_U&{Xv}O!9U3IcQjr)OH!7}0lo#_@_P!vLqCd{EPl-R>!rk0f9H$-${-LxP3|rf zCSED8@wg@^L&+ji<}!=Wt|MMTux5aW`W?U}lRknL7?~)z$$jNbdG!bneG#vkf^73l zC;T{-q8kSzBPUL3a$pdb-p+sqb^b$zOMQ1+R|+b)33ZItZjrkkH8(6@YcbH5LSIVm|ABx!%J_oOdz-#VV64pL zn@70G{gv|OF;lYyR-aPQ6^kB*AobzT_>+c2q}Dj zf(d?43;pNeSqfWX?T`Y^FGussVzPw7KA5>}r?4|Mg%$Q7zIlY3+;f#TkC_*rx592i zu_YAtF(`Kyc19_5h5}wK1+4yMb?*fXw;dJd`STjTfX%;1@ILpE`H+7(WGNG?3+E=QP9vYQYBq!GjB?ULRm%f%jc!ji(;*omtFA$MZ`-;l6;pu zB?2iJ=RdHui-J2J z3n@rpCMUCo9%0ozy|9I%@K) zD&N{Z7k8q;iz>)>$l5-*DpVSGQx(DD+DUKowemK~;+MvBzNxi6g}Q=x2}vrAReu#q z3dVh_7|(5VUxQB8J-%dIwU9z@WnGBp7aNCu3mp-ebm?@c2&9zCpAo9hlPdc^9xFNb;F*Sn zi+5!$UZ~%q)T==~)LvaC6BE6*S6Jrtj0p>0wyM6$}Wwym! z7eb$8VXqnbP1G;diRVIcLg+ILJ>SsPK3aSOlEElsD!=R@CACBoC=pMefkP&GjhhCpHp-_=U7Y45r}yE1cDutR-bXa#_ymTtS< zFs{~i)~eAb=B_mKHL(ie9fbKl`UE;V%Cjk5DQi8vBlfIVp5vcJ`QjhR7kk!zQ0t=- z)W#hK9lr%>X3?giC#n}law@Ur&R`$$|8=E7rR z`RWSY&VglBJ^M)}TnfX&J9J7hI7zSF7>`F=W>fzMdqu`tZM@}H*%*dV9V$aR`&CHd z)!Dn)#rKrOYM|vSgIQ?N$9+oA+k@_oLlX|p^Bbd2ZHMhusJ&pj7G{Lo-N)mXJ8OjD zzj3>?!&l>0wjPkxj**SgHQ+UW4H^;Qmlmg~?$cCw^-?wCQ91&;9Y8n0bPVd)wWB`{ z2u<(khrfNa)=r{yb5_vs!nIa*G;zWs6Z~{yiYQd0{S`dcZ0_0GU8j&-EH)sZv;5@r z5Sqy`(-I0X+I~IELOn#es&UN_?Qkm*lqCA!jP}o8`v5DtW+*w6Ev@0+{w`8+usb}c zo?l}M3B+-OeCNOkmDu=dS&zrAfZ9kQ?_ZSOz&Z33 zW1=+$IS2s?>#690Vjfu6Se^W8F!GkkF@o(lt%eJV*b^fqz5|-*#iSOa!ahlxS*xlj;sBk0MthodGlfQ!l zfIf$XYf^$N{(eV<$_CGRw3ec{+2BbvFg9N;FpwEb(c_%UajX01FLR~Sy~O-_*~bNk zfQ4pTUwW|;UV86SW3K|pvzuOriys$rsjlfXA2K%f{IM4#))^EPYLr*rz^-7AIdm8O zVu!+_nk;MUo3M`z=TivNLA|P*s{i#v781%fZ88QDn9JIRO)Yux6TZWb`x_b3prMj8 zM0q4%M(IQ>ZoAXq%Id$je#)=sV_ea>HRBP|!57bmKPb4c8OCPd&0Db(#G4>VqnACggeqrI|7 zitYyI@d;EdmSS7jpvvw5ml<^7VnP0cVKQk}0q&pF#~llk_H`7#P73uWm>nG}ieaT- zNBkOh&*dSFeg~0DI=f7xJO;)6hO49TN>u>%vp`joF7WmEI3CB=L5*EY#;P7KL`b3@ zb02^nb-xcJ(NA)~eFGjF$h9ZWPm$#^l>?<>t~8;%yZH%{=*Q7c^Flo{WS`# zDOOmD?_lpZ+iP%;;s~aQ&rEl(W0KzoN#~CVd)08q-oL<^ed;R2LP){d#51P=N6|CoQeBt&u@GUX$uG zQasuy4pE9n8%1e>Jc>JknpeHuLja5kwHT-^4ss^7f1acKz4w&xm)#S!%rLdp0Q%HA zt_(5uq>;KyNqLOHo_tY#p8DOdJ54qsJ^txh9KI-5?Z^fxk;Tjcj57+wnPROg?f?jN z7IA&&Fx}|u4{uhD(qBv>*?p-Eqzo7!Z3RgWNv@ zIxcn@yl8ANo1wp>PK-q*gZumog^3T`A0eJB+6<-5!|7V|u1{DA2t%JfxdCo?_aK9A}9;Y7(aS4RIc zp0Cki3-ydWZ{YcAFybrvbf~3wMRR^W%=6@cXMULmML#zwndkZUdOUv$pQ%L#roAmn z{~`BJqFq(F!F^wF|5wb1``lMRKfQB*JD_3icM7z2@hPn4t9`wOj z5sDY5f(}WsE;JR_*{gZyphwNVha=J42z8@<_Kg+yAi~Mtz}@-FKJ6>(nD}7$!i^En&GRDVh8Gl5dt#C<*4C(I?euu}pg|?&JW#M1#JO_5({6Yk7 z30~%Gm>znK8($w1asN^dc>I`kct*2Sc(1nAmt#uXJK=h!doX(YektsP68B5t6r>qz zY34}(^A+u{YgOGJ8Cg~Rnu?1LEWqCD#HxC31+=JA)rcF>j%SerBPST*l-i zjO?YK=~klt`y9WmHCCC|ZH`sYDo_N?T1+Q!_T#pz-OZR<_Zj>EBKizQ1zg2s?wdfdpWT!? z^b@3ma~mA+*H;Q_;K|+i8wUQ=xn1`sYRStR9c7Ltz~78Q3d}~P87K45P|XMtA_814 zgB{puNl|O0AphlT~{v+F#(oU zj}LeVTW{ubmBDuR`5IP_1!h8;4Du_3d{ykRK3o?qoV0}o8ETOE@@qPnkX_HAD<~Bi zY%7Lxl<-lX(x`fDrXb{8gM4I=GZQG~)U%TU*wF@i#$bmg!1C&MR#<<7%{5qR0&GHk ze}#QkVgAHmyZC%fuHQu=%MEg}LDt{qDdC*@T@~_2gY0jRz33yX3w3^dhJtP}(D&3c zRIrKF)<9G0*=d4w`38E=KyQRVm(}m4plk!x8mJ}&npVHNf_65LW1ypbwy&w*Lm}=x zD*QBqw8^hmcGK$zC~TR*#u{u%0&HgeK!rVMuzd`+e75Q7_F@3)_f%AYp*B;|(87El zHHWCZ6m`0x-Za!H;Vk74@_P1(p|GKbTF;VhT6uV1MBMTl|=naQMHE3HdL#Rx}T`Qin_~CI~nR}AH@M<{l1F2%uwrCJkZBn zA5}%veu_HLQ1ym-t}KvpK5=rnfRnbT;qEuwi9WSzqO$M@I@=gmT}(IBARqNGQ9oDI zYlb?_P|M}ltfQia$O9BvZOAM`RwW?$xkA0n$2e&-4EYVU4{5)IYqB~}!H#kLP^Eaf z;odY{V+i*WaR(~yAj3UoxCJ3x191l_Zrfayc(&mVn&p-23Zf2HRI8yT8>&TqJ&Bu% z9Hz)84SBdBHGdD;Lga8omKrkEkh2nKwi0=WBF{DCM=TBK=F9|S82md4p&^A;YJxQJA~Uz+!2baFkGhL zG=EP!okV6Ua;hOeXL&&8yKnKzg+0OgBNdfns0Kr6{vN$_B9Bt!o`$^NqX&oVX(p4n zqZRk%T`KW)hSU5#ii3z8smK+E%r)fkA&ObV9izDUh8t|S0U_K_;*M2Zf#EjasuFL2 zXY)85M%*tHH_mV?4YwkM8$sMC#SJywLc`4u;j)Pvt+*{Qm3Wrn3PQM%#2u%&Rfd~r zxN#xeDB{K_Zjs?e7;e=}ujGy=>Uc%nVW@tFdeTRoK$J{hI%!i3)yC3?6_op^6Nx%e zX&q;%7Yucj(DceIhscu@nQ6!hL#8Jn^N7q*-y(BPv%>CmU+Hp|0{#R}vLf)L=u+ zH&m{Vx{9b%6!p!WD(?(KeJQ`5yu6a7{#S}zX~=PgT#YNDaUo`BN)Jr2u>{IwzvG2|0Q?@XUw1ySP^m1?L` zLyhoJzawhAqSoA@db!Y0{e0BDM4hgvIzx>zR5m=cC+R%m&QM&1;W7?5N;uHXDMz|naX;D z;r8*lt08KlqE;GeoS|08uU8JWMCL2<5knqe$kz%yY3qoZq^Mbj+Ct4j+J!!92~lS& zYLcPeH`M6~xi%0vS&<_QxyX=16OheBo}U7-^;HjNehwZDzddyH8a_e6X46e z5@{vwJjK--F57T52^8CiJYSJ_7*gyBQqN96x4tpMkf$UdM-h3oB8M7sp&poQF(7MVK=qVnap@IWqw{g~;iOoMg!NSr)K_ z(-V->h`e5rBMiC7kV6xY(}}!6k$nt#yCDzprI|_8jfz@btlBx>P^;wE(@rsw1&Vyy zkVhHvi3DUhk%fvZH)OgYixZF)M9xs;g@#;1yMf&A!<%_Epo+Mg6nCuQo-^E&A>4f8 zW-4x1!`*GT$MDNzRCXx$Ma12z zxC+B%8ZJGAt0iuh;-(qSWr;xQHuxt`>czwrDK5uw4TjVFy|Sqza<(G(H01q;Jn=eD zjs~J`Q`E-UD(!Sb4f0Vu<)gk>QLh>5G(&B=)}ytYs5y#SXsDrv8XS^g1#!14ZkFM; zP_vM=K=7Un%|wJz?j{e`HHe8(0#MWgUE_CvzTg4=FC!a4QV=QV2JWxCM$EY&fwe(96Bjv#SY2{ZUch z+^q7>Flt}QuP5(hBC8d-(vaf}xp|sLZwgTlE9x;ri9I3L{X*PbM%*Kcn{BvlSE;n$ z!25a9P9yG5ikoD(_YL=E2zL!}3l(>`;hr?yV9 z%Y}xU6vE9U?s3IEXSibxr}=yOD<-l=k#h~%-;ky9>mkdD{Ieo2G32K#G3f9kctTG% z6~sNExZ@1>g5jPH;pP$d7sc&vxO)wER|r={+#9Y78-7T2v)O`hO4S68ECwDh!utIQm}?w}H5q z6gSOqE-e6bD=zaaYa>xh6?L+qmK*9gq3X%oNo2hu2N|-;kU2iRNGeb-D{51LN^ygs zu7aobxJxCjL2<7c?li+`{$9T6L@rZgwIQ<%srh@zOd^*na)u$lxm+ct|Ml`7MBFQi zJKb<^8m=*f8%*2^#T{h0#|*b1gv%oCRmE+)QDvTOIQoAt-=V}cD(-#5O)}iJOS}>p zMpTocY7Lcbs9_;$BZzBOT)E-W4Oc9`o?fzv{F@>#G~^nV7%V~a_mHEAd`*!f4Y}Bm zBNAxl5c#?ycQWK%hP)jf*poSrxRr|g^aj<kK){kl7)MlZks% zaTSKkG+f=qo)*t1>MccGWvKO+s?7KLs0)Z{QBRv79UA9W#7Z!2m)LoG1Wo(VEc zA@UtXZoXcnEimK;`SqloM&!GSe9e%j8FG07aypT#6j^P^EJIc$AZHT!o+4)$@*CO} z%K5qkWHFKND{`D6R~j-m0a;Gu2Z}tvkdGL0p9EwDk*$jCoUXFZG~`D4^<=Li@Vk1Rn!u-T2T`XwaQSleANE| z<$qa`&253P!gUzWySlLlyF~}_jif)I3hen%3`k3g)z zwxyL6bw&!$cMHQDOitwBoG=Gd0}c*S4&FIDnS(miL*-x_*G#ed&DT?AtY}NDu(PCS zOG@DtbBa1~hDW6ELX0J@xmImqZY5I02Oe07S0`XVTrN8xq}K1ZLtZd`m|av z3_)0HY=Ul-)nkfUWRukgZjNVWa$1NU#5V$A9sB7nEqIG_%ahYk z9y{ACTd@Equ>Jdhz_X@ZNyEhuI^r9TCA-YCvY>0o#V5tT%Lv2 zfl9Yp@|z-tC*W9f%Lrmv8Uz--Z7#f_KUA1MeMqy^iN@yg$c4(Qb(Mhm!(@)ZBzX z(7P1@#(N}*_t4H>jz}VTG2C;b$0mXMW+&3sj4iY6I+DXqP<+ji*k*wI`B1gPhRvee zLQM*yPhfOpY;5(|;VS}AxZMG$^StfS_>j?&l-98sPp!ax8Xx2T!v>;0uleqi3*>}K zcT>h>o>hr6EO9^&SjI^`D!`cNI@$D`Q8os(nvNLQ%w4`fRh*hJahbd3Z2IaE^s&wS zFf+WH)cfLZ6ue&@0Co6^6OH(u@)*I!X}a7xnp-*A0#AXh-a|`MlpR>qaikPYHn+dW z7LtiXlPeQdwdq{bf<-qcM!(DGK$AVwcoQwP6UmK_=slai5Hcv>A}O1>LLuX+SH{NA zPYY2=f?Y1Klm;!8O&NzYK(FIb29uYu99ny&KO!mnBqi)3bbWj2S<2>fepJdw3F%$R zJA}fIN_mmMlBI0%q{PRCEAeGrS9GNo@|fsKv$nl>@`aj=e=v6J?cvK}%}^Eo;Z)U4 z85ahsf@$@FLuQJjjl!EpYni&%9hxteOGUQ^p}T4*zNf?0GaqS_@`UyRph`A(IO~oV zABDa+_3V5y?7SvcxDa2RR)K1blfO{<95r4q;rbHsVtgM#v%gr{Apj$Jm*V@()KAoh zVE*A({M;HJyt-_c;=hFdd8H#`T`O?iL_g#3V~UJ-0VY&&5cmM@w%u zOQ)I2Cq1xIwyUdscfXuGN#J+{{w;6W-|>-;*>YEOHF*`$iRPi3nCoQqnsEVU ztir4(5zS{bdMBTZ9sa7v$Fh^Ro1~BM5&LNP@>ol5tRv&8)?PFJ;5TG$SP-9-`}2rL zwT3om`1#K$IS}p?6y4Gs#dLQ^P z9P+U?xebNUbb`B1PQXe*;G}`q&mKETz0#ZwqiA#JXuw5R$MWan43`Q_bW~xYqa1{4 zP)n=z+?pCEf4)v|RFKnkVr*C03zJ^@L4}RaE(~>9Go3fM(3hSVc8rTo?0p z{*1)yljX}we#)6qx)b(72v@}f#-gSALJ~ZJiPFfq+_AD*=tSu|bB@V%b^6XN4Y9HU zKb}0t^v*v?Pk~}(*I0aBiCfI_$UU8PC?daP`sA9Ia=XcA(k#mdI{xi@4n_xrJ`FgDht8Eep=@)(4upg4DsFLQ?$OANJw`($Q1an2FO z#tohBR8kWNo94*Pn+TiYR8m@mO?Kiu)(T-0oJz`xuskO|S;KOiN=k^ZQ4Wq65nQ%Y zN!buKEH^f5XjX2lVCbOS*fm2l{zoc<Gppv3>j_cKjP* zKyAWt$K&SBJ8o{Sgcv8=9h0#_cU+4SfqcCr6i+ne4~;aw0gwrjU15{}ebzYcIw6 z{6uhzlao3o`cl#1KM^m)PfqQ^)vI0TeO~aArV|5r2yMscSL7;{jI!OR$>>Vw0#lA4 z{xBhg7$xKQw2LMU!QDH>>}1jF(nDrEm$uvcL-1O78p*@KgmSs_0yB)X1CcV%$;loY z`|wnrMUBHi2TtCHl{XWrj-T+xdqW~p+uT2KzBDK!>K=e&76CxZ9dH9?0Qa(a-YYN{ zWFJBE`<@D%^TKvjhC^d79D7lZbCYZ$t;g?zCA8D{p6d$96z^56$o?q;GbU1iweB`d zfPg8+OBM4@8JJ}8Yy9|Pnm_6DI04}G9a$XeWnpupzs8hXc dd>o5Fo1{GN7Ch=T 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 Ok6yTDsrjA=^ zx?52}?KZNZmSzJ@OKFLP8$m&#w&?JR$@Lvem$Y|X)zn3P@2#k&p*@ye!WN}LR7?v` z$NG2@*4*13oSPY1Lpk*x)B(|AR39~M$%}e%kOePeb#yP`?kc&I5JeK5y?0``dRb6C ze7a9(_;gyIl$e)qy@|BvOlxRZ(zUdqxxc@nqM@O+i<@~v`{G#(`g-XcqM@O^FIefC zHNT;DYD3sf*Dk89ZirU1<}I2LS8Rv;)RTHc}_ zwmDzXm!Cx|d{n`)1q=G6wqkOWK|_0IPsglz)eW;3m7{Xf^3`C)lFloUDXoJ9D*zY z`O-N!Ih7Z FEuK69T{KPT+<66eyjwaeztZ^!krg#Ye>!u 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 literal 0 HcmV?d00001 diff --git a/plugins/libzm_plugin_face_haar/src/face_detector_plugin.cpp b/plugins/libzm_plugin_face_haar/src/face_detector_plugin.cpp new file mode 100644 index 000000000..48d94bf22 --- /dev/null +++ b/plugins/libzm_plugin_face_haar/src/face_detector_plugin.cpp @@ -0,0 +1,400 @@ +#include "face_detector_plugin.h" + + + +//! Retrieve the engine version we're going to expect +extern "C" int getEngineVersion() +{ + return ZM_ENGINE_VERSION; +} + +//! Tells us to register our functionality to an engine kernel +extern "C" void registerPlugin(PluginManager &PlM, string sPluginName) +{ + PlM.getImageAnalyser().addDetector( + auto_ptr(new FaceDetectorPlugin(sPluginName)) + ); +} + + + + +FaceDetectorPlugin::FaceDetectorPlugin() + : Detector(), + m_fScaleFactor(DEFAULT_HAAR_SCALE_FACTOR), + m_nMinNeighbors(DEFAULT_HAAR_MIN_NEIGHBORS), + m_nFlag(DEFAULT_HAAR_FLAG), + m_fMinObjWidth(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_WIDTH), + m_fMinObjHeight(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_HEIGHT), + m_cascade(NULL), + m_sHaarCascadePath(DEFAULT_HAAR_FACE_CASCADE_PATH) +{ + m_sDetectionCause = DETECTED_CAUSE; + m_sLogPrefix = LOG_PREFIX; + + //openlog(m_sLogPrefix.c_str(), LOG_PID|LOG_CONS, LOG_USER); + m_pStorage = cvCreateMemStorage(0); + //_loadHaarCascade(m_sHaarCascadePath); + log(LOG_NOTICE, "Face Detector Plugin\'s Object has been created."); +} + + + + +FaceDetectorPlugin::FaceDetectorPlugin(string sPluginName) + : Detector(sPluginName), + m_fScaleFactor(DEFAULT_HAAR_SCALE_FACTOR), + m_nMinNeighbors(DEFAULT_HAAR_MIN_NEIGHBORS), + m_nFlag(DEFAULT_HAAR_FLAG), + m_fMinObjWidth(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_WIDTH), + m_fMinObjHeight(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_HEIGHT), + m_cascade(NULL), + m_sHaarCascadePath(DEFAULT_HAAR_FACE_CASCADE_PATH) +{ + m_sDetectionCause = DETECTED_CAUSE; + m_sLogPrefix = LOG_PREFIX; + + //openlog(m_sLogPrefix.c_str(), LOG_PID|LOG_CONS, LOG_USER); + m_pStorage = cvCreateMemStorage(0); + //_loadHaarCascade(m_sHaarCascadePath); + log(LOG_NOTICE, "Face Detector Plugin\'s Object has been created."); +} + + + +/*! \fn FaceDetectorPlugin::loadConfig(string sConfigFileName) + * \param sConfigFileName is path to configuration to load parameters from + */ +void FaceDetectorPlugin::loadConfig(string sConfigFileName) +{ + options_description config_file("Configuration file options."); + variables_map vm; + config_file.add_options() + // Haar face detector options + ((m_sConfigSectionName + string(".cascade")).c_str(), + value()->default_value(DEFAULT_HAAR_FACE_CASCADE_PATH)) + ((m_sConfigSectionName + string(".scale")).c_str(), + value()->default_value(DEFAULT_HAAR_SCALE_FACTOR)) + ((m_sConfigSectionName + string(".flag")).c_str(), + value()->default_value(DEFAULT_HAAR_FLAG)) + ((m_sConfigSectionName + string(".min-nbrs")).c_str(), + value()->default_value(DEFAULT_HAAR_MIN_NEIGHBORS)) + ((m_sConfigSectionName + string(".min-obj-width")).c_str(), + value()->default_value(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_WIDTH)) + ((m_sConfigSectionName + string(".min-obj-height")).c_str(), + value()->default_value(DEFAULT_DETECTOR_MIN_OBJECT_SIZE_HEIGHT)) + ((m_sConfigSectionName + string(".min-alarm-score")).c_str(), + value()->default_value(DEFAULT_MIN_ALARM_SCORE)) + ((m_sConfigSectionName + string(".max-alarm-score")).c_str(), + value()->default_value(DEFAULT_MAX_ALARM_SCORE)) + ((m_sConfigSectionName + string(".image-scale-factor")).c_str(), + value()->default_value(DEFAULT_IMAGE_SCALE_FACTOR)) + ((m_sConfigSectionName + string(".det-cause")).c_str(), + value()->default_value(DETECTED_CAUSE)) + ((m_sConfigSectionName + string(".log-prefix")).c_str(), + value()->default_value(LOG_PREFIX)) + ; + ifstream ifs(sConfigFileName.c_str()); + store(parse_config_file(ifs, config_file, true), vm); + notify(vm); + + m_fScaleFactor = vm[(m_sConfigSectionName + string(".scale")).c_str()].as(); + m_nMinNeighbors = vm[(m_sConfigSectionName + string(".min-nbrs")).c_str()].as(); + m_nFlag = vm[(m_sConfigSectionName + string(".flag")).c_str()].as(); + m_fMinObjWidth = vm[(m_sConfigSectionName + string(".min-obj-width")).c_str()].as(); + m_fMinObjHeight = vm[(m_sConfigSectionName + string(".min-obj-height")).c_str()].as(); + m_fMinAlarmScore = vm[(m_sConfigSectionName + string(".min-alarm-score")).c_str()].as(); + m_fMaxAlarmScore = vm[(m_sConfigSectionName + string(".max-alarm-score")).c_str()].as(); + m_fImageScaleFactor = vm[(m_sConfigSectionName + string(".image-scale-factor")).c_str()].as(); + + m_sDetectionCause = vm[(m_sConfigSectionName + string(".det-cause")).c_str()].as(); + m_sLogPrefix = vm[(m_sConfigSectionName + string(".log-prefix")).c_str()].as(); + +// if (m_sHaarCascadePath != vm[(m_sConfigSectionName + string(".cascade")).c_str()].as()) +// { + m_sHaarCascadePath = vm[(m_sConfigSectionName + string(".cascade")).c_str()].as(); + _loadHaarCascade(m_sHaarCascadePath); +// } + zmLoadConfig(); + log(LOG_NOTICE, "Face Detector Plugin\'s Object is configured."); +} + + + +FaceDetectorPlugin::~FaceDetectorPlugin() +{ + cvReleaseMemStorage(&m_pStorage); + cvReleaseHaarClassifierCascade(&m_cascade); +} + + +/*! \fn FaceDetectorPlugin::FaceDetectorPlugin(const FaceDetectorPlugin& source) + * \param source is the object for copying + */ +FaceDetectorPlugin::FaceDetectorPlugin(const FaceDetectorPlugin& source) + : Detector(source), + m_fScaleFactor(source.m_fScaleFactor), + m_nMinNeighbors(source.m_nMinNeighbors), + m_nFlag(source.m_nFlag), + m_fMinObjWidth(source.m_fMinObjWidth), + m_fMinObjHeight(source.m_fMinObjHeight), + m_cascade(NULL), + m_sHaarCascadePath(source.m_sHaarCascadePath) +{ + m_pStorage = cvCreateMemStorage(0); + if (m_sHaarCascadePath != string()) + _loadHaarCascade(m_sHaarCascadePath); +} + + + +/*! \fn FaceDetectorPlugin:: operator=(const FaceDetectorPlugin& source) + * \param source is the object for copying + */ +FaceDetectorPlugin & FaceDetectorPlugin:: operator=(const FaceDetectorPlugin& source) +{ + Detector::operator=(source); + m_fScaleFactor = source.m_fScaleFactor; + m_nMinNeighbors = source.m_nMinNeighbors; + m_nFlag = source.m_nFlag; + m_fMinObjWidth = source.m_fMinObjWidth; + m_fMinObjHeight = source.m_fMinObjHeight; + m_cascade = NULL; + m_sHaarCascadePath = source.m_sHaarCascadePath; + + m_pStorage = cvCreateMemStorage(0); + + if (m_sHaarCascadePath != string()) + _loadHaarCascade(m_sHaarCascadePath); + + return *this; +} + + + +/*! \fn FaceDetectorPlugin::_loadHaarCascade(string sConfigPath) + * \param sConfigPath is path to xml Haar classifier cascade. + */ +void FaceDetectorPlugin::_loadHaarCascade(string sConfigPath) +{ + m_sHaarCascadePath = sConfigPath; + if (m_cascade != NULL) + cvReleaseHaarClassifierCascade(&m_cascade); + + m_cascade = (CvHaarClassifierCascade*)cvLoad(sConfigPath.c_str()); + if (m_cascade == NULL) + throw invalid_argument((string("Couldn't load xml data: ") + sConfigPath + ".").c_str()); +} + + + + +/*! \fn FaceDetectorPlugin::_opencvHaarDetect(const CvMat* pMatImage) + * \param pMatImage is an image to perform face detection (in the form of OpenCv' CvMat) + */ +vector FaceDetectorPlugin::_opencvHaarDetect(const CvMat* pMatImage) +{ + CvSize minObjSize = cvSize((int) pMatImage->width * m_fMinObjWidth / 100.0, (int) pMatImage->height * m_fMinObjHeight / 100.0); + //char szMessage[50]; + //sprintf(szMessage, "IMAGE SIZE IS %d x %d \nMIN OBJ SIZE IS %d x %d", pMatImage->width, pMatImage->height, minObjSize.width, minObjSize.height); + //log(LOG_WARNING, szMessage); + + CvSeq* haarObjects = cvHaarDetectObjects(pMatImage, + m_cascade, + m_pStorage, + m_fScaleFactor, + m_nMinNeighbors, + m_nFlag, + minObjSize); + vector objects; + for (int i = 0; i < haarObjects->total; i++) + { + CvRect* pHaarRect = (CvRect*)cvGetSeqElem(haarObjects, i); + objects.push_back(*pHaarRect); + } + return objects; +} + + +/*! \fn FaceDetectorPlugin::checkZone(Zone *zone, const Image *zmImage) + * \param zone is a zone where faces will be detected + * \param zmImage is an image to perform face detection (in the form of ZM' Image) + * \return true if there were objects detected in given image and + * false otherwise + */ +bool FaceDetectorPlugin::checkZone(Zone *zone, const Image *zmImage) +{ + //log(LOG_DEBUG, "Entering checkZone."); + double score; + Polygon zone_polygon = Polygon(zone->GetPolygon()); // Polygon of interest of the processed zone. + //char szMessage[50]; + //sprintf(szMessage, "Polygon of the zone has %d vertices.", zone_polygon.getNumCoords()); + //log(LOG_WARNING, szMessage); + + //zone->ResetStats(); + + /* + log(LOG_WARNING, "precheck"); + if ( !zone->CheckOverloadCount() ) + { + log(LOG_WARNING, "CheckOverloadCount() return false, we'll return false."); + return(false); + } + */ + //zmLoadConfig(); + // An image for highlighting detected objects. + Image *pMaskImage = new Image(zmImage->Width(), zmImage->Height(), ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ); + pMaskImage->Fill(BLACK); + + //log(LOG_WARNING, "FILLBLACK."); + // An temporary image in the form of ZM for making from it CvMat. + // If don't use temp image, after rgb->bgr it will change. + Image *tempZmImage = new Image(*zmImage); + CvMat* cvInputImage = NULL; + CvMat* pScaledImage = NULL; + + bool bDoResizing = (m_fImageScaleFactor != 1.0); // resize image or not + + if (tempZmImage->Colours() == ZM_COLOUR_GRAY8) + { + // if image is not colored, create an one-channel CvMat. + cvInputImage = cvCreateMat(tempZmImage->Height(), tempZmImage->Width(), CV_8UC1); + unsigned char *buffer = (unsigned char*)tempZmImage->Buffer(); + cvSetData(cvInputImage, buffer, tempZmImage->Width()); + } + // NEXTIME XXX TODO: manage also 32 bit images! + else + { + // otherwise create a three-channel CvMat and then convert colors from RGB to BGR. + cvInputImage = cvCreateMat(tempZmImage->Height(), tempZmImage->Width(), CV_8UC3); + unsigned char *buffer = (unsigned char*)tempZmImage->Buffer(); + cvSetData(cvInputImage, buffer, tempZmImage->Width() * 3); + cvCvtColor(cvInputImage, cvInputImage, CV_RGB2BGR); + } + + if (bDoResizing) + { + int nNewWidth = int (m_fImageScaleFactor * zmImage->Width()); + int nNewHeight = int (m_fImageScaleFactor * tempZmImage->Height()); + int nImageElemType = cvGetElemType(cvInputImage); + pScaledImage = cvCreateMat(nNewHeight, nNewWidth, nImageElemType); + cvResize(cvInputImage, pScaledImage, CV_INTER_LINEAR); + } + + + //Process image + + vector foundObjects; + if (bDoResizing) + foundObjects = _opencvHaarDetect(pScaledImage); + else + foundObjects = _opencvHaarDetect(cvInputImage); + + if (foundObjects.size() > 0) + log(LOG_INFO, "OBJECTS WERE DETECTED"); + + score = 0; + for (vector::iterator it = foundObjects.begin(); it < foundObjects.end(); it++) + { + // Process found objects. + + // Scale object's coordinates back if image has been scaled. + int x1 = int(it->x/m_fImageScaleFactor), x2 = int((it->x + it->width)/m_fImageScaleFactor), y1 = int(it->y/m_fImageScaleFactor), y2 = int((it->y + it->height)/m_fImageScaleFactor); + + // Check if object's rectangle is inside zone's polygon of interest. + Coord rectVertCoords[4] = {Coord(x1, y1), Coord(x1, y2), Coord(x2, y1), Coord(x2, y2)}; + int nNumVertInside = 0; + for (int i = 0; i < 4; i++) + { + nNumVertInside += zone_polygon.isInside(rectVertCoords[i]); + } + if (nNumVertInside < 3) + // if at least three rectangle coordinates are inside polygon, consider rectangle as belonging to the zone + // otherwise process next object + continue; + + // Fill a box with object in the mask + Box *faceBox = new Box(x1, y1, x2, y2); + pMaskImage->Fill(WHITE, faceBox); + // Calculate score as portion of object area in the image + score += (100.0*(it->width)*(it->height)/m_fImageScaleFactor/m_fImageScaleFactor)/zone_polygon.Area(); + delete faceBox; + } + + + if (score == 0) + { + //log(LOG_DEBUG, "No objects found. Exit."); + delete pMaskImage; + delete tempZmImage; + + if (cvInputImage) + cvReleaseMat(&cvInputImage); + if (pScaledImage) + cvReleaseMat(&pScaledImage); + + return( false ); + } + + + + if ( m_fMinAlarmScore && ( score < m_fMinAlarmScore) ) + { + delete pMaskImage; + delete tempZmImage; + + if (cvInputImage) + cvReleaseMat(&cvInputImage); + if (pScaledImage) + cvReleaseMat(&pScaledImage); + + return( false ); + } + if ( m_fMaxAlarmScore && (score > m_fMaxAlarmScore) ) + { + zone->SetOverloadCount(zone->GetOverloadFrames()); + delete pMaskImage; + delete tempZmImage; + + if (cvInputImage) + cvReleaseMat(&cvInputImage); + if (pScaledImage) + cvReleaseMat(&pScaledImage); + + return( false ); + } + + + zone->SetScore(max(1, (int)score)); + + //Get mask by highlighting contours of objects and overlaying them with previous contours. + Rgb alarm_colour = RGB_GREEN; + Image *hlZmImage = pMaskImage->HighlightEdges(alarm_colour, ZM_COLOUR_RGB24, + ZM_SUBPIX_ORDER_RGB, &zone_polygon.Extent()); + + if (zone->Alarmed()) + { + // if there were previous detection and they have already set up alarm image + // then overlay it with current mask + Image* pPrevZoneMask = new Image(*(zone->AlarmImage())); + pPrevZoneMask->Overlay(*hlZmImage); + zone->SetAlarmImage(pPrevZoneMask); + delete pPrevZoneMask; + } + else + zone->SetAlarmImage(hlZmImage); + + delete pMaskImage; + delete hlZmImage; + delete tempZmImage; + + if (cvInputImage) + cvReleaseMat(&cvInputImage); + if (pScaledImage) + cvReleaseMat(&pScaledImage); + + //log(LOG_DEBUG, "Leaving checkZone."); + return true; +} + + diff --git a/plugins/libzm_plugin_face_haar/src/face_detector_plugin.h b/plugins/libzm_plugin_face_haar/src/face_detector_plugin.h new file mode 100644 index 000000000..ccb9b9f04 --- /dev/null +++ b/plugins/libzm_plugin_face_haar/src/face_detector_plugin.h @@ -0,0 +1,102 @@ +#ifndef HAAR_DETECTOR_PLUGIN_H +#define HAAR_DETECTOR_PLUGIN_H + + +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "zm_plugin_manager.h" +#include "zm_detector.h" +#include "zm_rgb.h" + + + +#define DETECTED_CAUSE "Face Detected" +#define LOG_PREFIX "ZM FACEDET PLUGIN" + + +#define DEFAULT_HAAR_SCALE_FACTOR 1.1 +#define DEFAULT_HAAR_MIN_NEIGHBORS 3 +#define DEFAULT_HAAR_FLAG CV_HAAR_DO_CANNY_PRUNING +#define DEFAULT_DETECTOR_MIN_OBJECT_SIZE_WIDTH 5.0 +#define DEFAULT_DETECTOR_MIN_OBJECT_SIZE_HEIGHT 6.0 +#define DEFAULT_HAAR_FACE_CASCADE_PATH "/usr/local/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml" + + + + +using namespace std; +using namespace boost::program_options; + + +//! Face detector plugin class. +/*! The class derived from Detector. + * This class provides face detection based on OpenCV's implementation of Haar cascade classifier detector. + */ +class FaceDetectorPlugin : public Detector { + public: + + //! Default Constructor. + FaceDetectorPlugin(); + + //! Constructor. + FaceDetectorPlugin(string sConfigSectionName); + + //! Destructor. + virtual ~FaceDetectorPlugin(); + + //! Copy constructor. + FaceDetectorPlugin(const FaceDetectorPlugin& source); + + //! Overloaded operator=. + FaceDetectorPlugin& operator=(const FaceDetectorPlugin& source); + + void loadConfig(string sConfigFileName); + +protected: + + bool checkZone(Zone *zone, const Image *zmImage); + + //! Path to the xml file with cascade. + string m_sHaarCascadePath; + + //! Cascade of classifiers. + CvHaarClassifierCascade* m_cascade; + + //! Scale factor. + double m_fScaleFactor; + + //! Minimum number (minus 1) of neighbors rectangles that makes up an object. + size_t m_nMinNeighbors; + + //! Mode of operation. + int m_nFlag; + + //! Minimal object's sizes. + double m_fMinObjWidth; + double m_fMinObjHeight; + + //! Pointer to storage for calculations. + CvMemStorage* m_pStorage; + +private: + + //! Load xml Haar cascade file. + void _loadHaarCascade(string sConfigPath); + + //! Detect faces on OpenCV' CvMat image. + vector _opencvHaarDetect(const CvMat* pMatImage); +}; + + + +#endif //HAAR_DETECTOR_PLUGIN_H + diff --git a/scripts/Makefile.am b/scripts/Makefile.am new file mode 100644 index 000000000..bbdcb282e --- /dev/null +++ b/scripts/Makefile.am @@ -0,0 +1,75 @@ +AUTOMAKE_OPTIONS = gnu + +# Ack! Nasty hack to get modules Makefile regenerated if wiped with make clean +all-local: ZoneMinder/Makefile + +ZoneMinder/Makefile: ZoneMinder/Makefile.PL + ( cd ZoneMinder; perl Makefile.PL ) + +bin_SCRIPTS = \ + zmdc.pl \ + zmaudit.pl \ + zmfilter.pl \ + zmtrigger.pl \ + zmx10.pl \ + zmwatch.pl \ + zmpkg.pl \ + zmupdate.pl \ + zmvideo.pl \ + zmcontrol.pl \ + zmtrack.pl + +SUBDIRS = \ + . \ + ZoneMinder + +EXTRA_DIST = \ + zmdc.pl.in \ + zmaudit.pl.in \ + zmfilter.pl.in \ + zmtrigger.pl.in \ + zmx10.pl.in \ + zmwatch.pl.in \ + zmpkg.pl.in \ + zmupdate.pl.in \ + zmvideo.pl.in \ + zmcontrol.pl.in \ + zmtrack.pl.in \ + ZoneMinder/Makefile.PL \ + ZoneMinder/README \ + ZoneMinder/Changes \ + ZoneMinder/META.yml \ + ZoneMinder/MANIFEST \ + ZoneMinder/t/ZoneMinder.t \ + ZoneMinder/lib/ZoneMinder.pm \ + ZoneMinder/lib/ZoneMinder/Base.pm.in \ + ZoneMinder/lib/ZoneMinder/Config.pm.in \ + ZoneMinder/lib/ZoneMinder/Logger.pm \ + ZoneMinder/lib/ZoneMinder/General.pm \ + ZoneMinder/lib/ZoneMinder/Database.pm \ + ZoneMinder/lib/ZoneMinder/Memory.pm.in \ + ZoneMinder/lib/ZoneMinder/Memory/Shared.pm \ + ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm \ + ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm \ + ZoneMinder/lib/ZoneMinder/ConfigData.pm.in \ + ZoneMinder/lib/ZoneMinder/Control.pm \ + ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm \ + ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm \ + ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm \ + ZoneMinder/lib/ZoneMinder/Control/Visca.pm \ + ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm \ + ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm \ + zm.in \ + zmdbbackup.in \ + zmdbrestore.in \ + zmeventdump.in \ + zmlogrotate.conf.in diff --git a/scripts/Makefile.in b/scripts/Makefile.in new file mode 100644 index 000000000..e6931d899 --- /dev/null +++ b/scripts/Makefile.in @@ -0,0 +1,778 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = scripts +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/zm.in $(srcdir)/zmaudit.pl.in \ + $(srcdir)/zmcontrol.pl.in $(srcdir)/zmdbbackup.in \ + $(srcdir)/zmdbrestore.in $(srcdir)/zmdc.pl.in \ + $(srcdir)/zmeventdump.in $(srcdir)/zmfilter.pl.in \ + $(srcdir)/zmlogrotate.conf.in $(srcdir)/zmpkg.pl.in \ + $(srcdir)/zmtrack.pl.in $(srcdir)/zmtrigger.pl.in \ + $(srcdir)/zmupdate.pl.in $(srcdir)/zmvideo.pl.in \ + $(srcdir)/zmwatch.pl.in $(srcdir)/zmx10.pl.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = zm zmaudit.pl zmcontrol.pl zmdc.pl zmfilter.pl \ + zmpkg.pl zmtrack.pl zmtrigger.pl zmupdate.pl zmvideo.pl \ + zmwatch.pl zmx10.pl zmdbbackup zmdbrestore zmeventdump \ + zmlogrotate.conf +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(bindir)" +SCRIPTS = $(bin_SCRIPTS) +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +bin_SCRIPTS = \ + zmdc.pl \ + zmaudit.pl \ + zmfilter.pl \ + zmtrigger.pl \ + zmx10.pl \ + zmwatch.pl \ + zmpkg.pl \ + zmupdate.pl \ + zmvideo.pl \ + zmcontrol.pl \ + zmtrack.pl + +SUBDIRS = \ + . \ + ZoneMinder + +EXTRA_DIST = \ + zmdc.pl.in \ + zmaudit.pl.in \ + zmfilter.pl.in \ + zmtrigger.pl.in \ + zmx10.pl.in \ + zmwatch.pl.in \ + zmpkg.pl.in \ + zmupdate.pl.in \ + zmvideo.pl.in \ + zmcontrol.pl.in \ + zmtrack.pl.in \ + ZoneMinder/Makefile.PL \ + ZoneMinder/README \ + ZoneMinder/Changes \ + ZoneMinder/META.yml \ + ZoneMinder/MANIFEST \ + ZoneMinder/t/ZoneMinder.t \ + ZoneMinder/lib/ZoneMinder.pm \ + ZoneMinder/lib/ZoneMinder/Base.pm.in \ + ZoneMinder/lib/ZoneMinder/Config.pm.in \ + ZoneMinder/lib/ZoneMinder/Logger.pm \ + ZoneMinder/lib/ZoneMinder/General.pm \ + ZoneMinder/lib/ZoneMinder/Database.pm \ + ZoneMinder/lib/ZoneMinder/Memory.pm.in \ + ZoneMinder/lib/ZoneMinder/Memory/Shared.pm \ + ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm \ + ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm \ + ZoneMinder/lib/ZoneMinder/ConfigData.pm.in \ + ZoneMinder/lib/ZoneMinder/Control.pm \ + ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm \ + ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm \ + ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm \ + ZoneMinder/lib/ZoneMinder/Control/Visca.pm \ + ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm \ + ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm \ + ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm \ + zm.in \ + zmdbbackup.in \ + zmdbrestore.in \ + zmeventdump.in \ + zmlogrotate.conf.in + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu scripts/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu scripts/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +zm: $(top_builddir)/config.status $(srcdir)/zm.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmaudit.pl: $(top_builddir)/config.status $(srcdir)/zmaudit.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmcontrol.pl: $(top_builddir)/config.status $(srcdir)/zmcontrol.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmdc.pl: $(top_builddir)/config.status $(srcdir)/zmdc.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmfilter.pl: $(top_builddir)/config.status $(srcdir)/zmfilter.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmpkg.pl: $(top_builddir)/config.status $(srcdir)/zmpkg.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmtrack.pl: $(top_builddir)/config.status $(srcdir)/zmtrack.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmtrigger.pl: $(top_builddir)/config.status $(srcdir)/zmtrigger.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmupdate.pl: $(top_builddir)/config.status $(srcdir)/zmupdate.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmvideo.pl: $(top_builddir)/config.status $(srcdir)/zmvideo.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmwatch.pl: $(top_builddir)/config.status $(srcdir)/zmwatch.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmx10.pl: $(top_builddir)/config.status $(srcdir)/zmx10.pl.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmdbbackup: $(top_builddir)/config.status $(srcdir)/zmdbbackup.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmdbrestore: $(top_builddir)/config.status $(srcdir)/zmdbrestore.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmeventdump: $(top_builddir)/config.status $(srcdir)/zmeventdump.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +zmlogrotate.conf: $(top_builddir)/config.status $(srcdir)/zmlogrotate.conf.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binSCRIPTS: $(bin_SCRIPTS) + @$(NORMAL_INSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n' \ + -e 'h;s|.*|.|' \ + -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) { files[d] = files[d] " " $$1; \ + if (++n[d] == $(am__install_max)) { \ + print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ + else { print "f", d "/" $$4, $$1 } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binSCRIPTS: + @$(NORMAL_UNINSTALL) + @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 's,.*/,,;$(transform)'`; \ + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(SCRIPTS) all-local +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: install-binSCRIPTS + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-binSCRIPTS + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am all-local check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-binSCRIPTS install-data install-data-am \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-binSCRIPTS + + +# Ack! Nasty hack to get modules Makefile regenerated if wiped with make clean +all-local: ZoneMinder/Makefile + +ZoneMinder/Makefile: ZoneMinder/Makefile.PL + ( cd ZoneMinder; perl Makefile.PL ) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/scripts/ZoneMinder/Changes b/scripts/ZoneMinder/Changes new file mode 100644 index 000000000..cc20050e5 --- /dev/null +++ b/scripts/ZoneMinder/Changes @@ -0,0 +1,6 @@ +Revision history for Perl extension ZoneMinder. + +0.01 Thu Dec 15 17:22:29 2005 + - original version; created by h2xs 1.23 with options + -XA -b 5.6.0 -n ZoneMinder + diff --git a/scripts/ZoneMinder/MANIFEST b/scripts/ZoneMinder/MANIFEST new file mode 100644 index 000000000..f1bd05da8 --- /dev/null +++ b/scripts/ZoneMinder/MANIFEST @@ -0,0 +1,7 @@ +Changes +Makefile.PL +MANIFEST +README +t/ZoneMinder.t +lib/ZoneMinder.pm +META.yml Module meta-data (added by MakeMaker) diff --git a/scripts/ZoneMinder/META.yml b/scripts/ZoneMinder/META.yml new file mode 100644 index 000000000..7d062554d --- /dev/null +++ b/scripts/ZoneMinder/META.yml @@ -0,0 +1,10 @@ +# http://module-build.sourceforge.net/META-spec.html +#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX# +name: ZoneMinder +version: 1.23.2 +version_from: lib/ZoneMinder/Base.pm +installdirs: site +requires: + +distribution_type: module +generated_by: ExtUtils::MakeMaker version 6.17 diff --git a/scripts/ZoneMinder/MYMETA.yml b/scripts/ZoneMinder/MYMETA.yml new file mode 100644 index 000000000..8d77ebdf2 --- /dev/null +++ b/scripts/ZoneMinder/MYMETA.yml @@ -0,0 +1,22 @@ +--- +abstract: 'Container module for common ZoneMinder modules' +author: + - 'Philip Coombes ' +build_requires: + ExtUtils::MakeMaker: 0 +configure_requires: + ExtUtils::MakeMaker: 0 +distribution_type: module +dynamic_config: 0 +generated_by: 'ExtUtils::MakeMaker version 6.57_05' +license: unknown +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 +name: ZoneMinder +no_index: + directory: + - t + - inc +requires: {} +version: 1.25.0 diff --git a/scripts/ZoneMinder/Makefile.PL b/scripts/ZoneMinder/Makefile.PL new file mode 100644 index 000000000..c7a7434c8 --- /dev/null +++ b/scripts/ZoneMinder/Makefile.PL @@ -0,0 +1,41 @@ +use 5.006; +use ExtUtils::MakeMaker; +# See lib/ExtUtils/MakeMaker.pm for details of how to influence +# the contents of the Makefile that is written. +WriteMakefile( + NAME => 'ZoneMinder', + VERSION_FROM => 'lib/ZoneMinder/Base.pm', # finds $VERSION + PREREQ_PM => {}, # e.g., Module::Name => 1.1 + PM => { + 'lib/ZoneMinder.pm' => '$(INST_LIBDIR)/ZoneMinder.pm', + 'lib/ZoneMinder/Base.pm' => '$(INST_LIBDIR)/ZoneMinder/Base.pm', + 'lib/ZoneMinder/Config.pm' => '$(INST_LIBDIR)/ZoneMinder/Config.pm', + 'lib/ZoneMinder/General.pm' => '$(INST_LIBDIR)/ZoneMinder/General.pm', + 'lib/ZoneMinder/Database.pm' => '$(INST_LIBDIR)/ZoneMinder/Database.pm', + 'lib/ZoneMinder/Logger.pm' => '$(INST_LIBDIR)/ZoneMinder/Logger.pm', + 'lib/ZoneMinder/Memory.pm' => '$(INST_LIBDIR)/ZoneMinder/Memory.pm', + 'lib/ZoneMinder/Memory/Shared.pm' => '$(INST_LIBDIR)/ZoneMinder/Memory/Shared.pm', + 'lib/ZoneMinder/Memory/Mapped.pm' => '$(INST_LIBDIR)/ZoneMinder/Memory/Mapped.pm', + 'lib/ZoneMinder/ConfigAdmin.pm' => '$(INST_LIBDIR)/ZoneMinder/ConfigAdmin.pm', + 'lib/ZoneMinder/ConfigData.pm' => '$(INST_LIBDIR)/ZoneMinder/ConfigData.pm', + 'lib/ZoneMinder/Control.pm' => '$(INST_LIBDIR)/ZoneMinder/Control.pm', + 'lib/ZoneMinder/Control/PelcoD.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/PelcoD.pm', + 'lib/ZoneMinder/Control/AxisV2.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/AxisV2.pm', + 'lib/ZoneMinder/Control/PanasonicIP.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/PanasonicIP.pm', + 'lib/ZoneMinder/Control/Visca.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/Visca.pm', + 'lib/ZoneMinder/Control/Ncs370.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/Ncs370.pm', + 'lib/ZoneMinder/Control/mjpgStreamer.pm' => '$(INST_LIBDIR)/ZoneMinder/Control/mjpgStreamer.pm', + 'lib/ZoneMinder/Trigger/Channel.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel.pm', + 'lib/ZoneMinder/Trigger/Channel/Handle.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Handle.pm', + 'lib/ZoneMinder/Trigger/Channel/Spawning.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Spawning.pm', + 'lib/ZoneMinder/Trigger/Channel/Inet.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Inet.pm', + 'lib/ZoneMinder/Trigger/Channel/Unix.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Unix.pm', + 'lib/ZoneMinder/Trigger/Channel/File.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/File.pm', + 'lib/ZoneMinder/Trigger/Channel/Serial.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Serial.pm', + 'lib/ZoneMinder/Trigger/Connection.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Connection.pm', + 'lib/ZoneMinder/Trigger/Connection/Example.pm' => '$(INST_LIBDIR)/ZoneMinder/Trigger/Connection/Example.pm', + }, + ($] >= 5.005 ? ## Add these new keywords supported since 5.005 + (ABSTRACT_FROM => 'lib/ZoneMinder.pm', # retrieve abstract from module + AUTHOR => 'Philip Coombes ') : ()), +); diff --git a/scripts/ZoneMinder/Makefile.old b/scripts/ZoneMinder/Makefile.old new file mode 100644 index 000000000..63b65fd11 --- /dev/null +++ b/scripts/ZoneMinder/Makefile.old @@ -0,0 +1,965 @@ +# This Makefile is for the ZoneMinder extension to perl. +# +# It was generated automatically by MakeMaker version +# 6.57_05 (Revision: 65705) from the contents of +# Makefile.PL. Don't edit this file, edit Makefile.PL instead. +# +# ANY CHANGES MADE HERE WILL BE LOST! +# +# MakeMaker ARGV: () +# + +# MakeMaker Parameters: + +# ABSTRACT_FROM => q[lib/ZoneMinder.pm] +# AUTHOR => [q[Philip Coombes ]] +# BUILD_REQUIRES => { } +# NAME => q[ZoneMinder] +# PM => { lib/ZoneMinder/Trigger/Connection.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Connection.pm], lib/ZoneMinder/Control/Ncs370.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/Ncs370.pm], lib/ZoneMinder/Trigger/Channel/Serial.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Serial.pm], lib/ZoneMinder/Memory/Shared.pm=>q[$(INST_LIBDIR)/ZoneMinder/Memory/Shared.pm], lib/ZoneMinder.pm=>q[$(INST_LIBDIR)/ZoneMinder.pm], lib/ZoneMinder/Config.pm=>q[$(INST_LIBDIR)/ZoneMinder/Config.pm], lib/ZoneMinder/Control/mjpgStreamer.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/mjpgStreamer.pm], lib/ZoneMinder/Trigger/Channel/Unix.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Unix.pm], lib/ZoneMinder/Control/PanasonicIP.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/PanasonicIP.pm], lib/ZoneMinder/Base.pm=>q[$(INST_LIBDIR)/ZoneMinder/Base.pm], lib/ZoneMinder/Control/AxisV2.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/AxisV2.pm], lib/ZoneMinder/Memory/Mapped.pm=>q[$(INST_LIBDIR)/ZoneMinder/Memory/Mapped.pm], lib/ZoneMinder/Trigger/Channel.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel.pm], lib/ZoneMinder/Memory.pm=>q[$(INST_LIBDIR)/ZoneMinder/Memory.pm], lib/ZoneMinder/Trigger/Channel/File.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/File.pm], lib/ZoneMinder/Database.pm=>q[$(INST_LIBDIR)/ZoneMinder/Database.pm], lib/ZoneMinder/ConfigData.pm=>q[$(INST_LIBDIR)/ZoneMinder/ConfigData.pm], lib/ZoneMinder/Control/PelcoD.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/PelcoD.pm], lib/ZoneMinder/Control/Visca.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control/Visca.pm], lib/ZoneMinder/Trigger/Channel/Inet.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Inet.pm], lib/ZoneMinder/Logger.pm=>q[$(INST_LIBDIR)/ZoneMinder/Logger.pm], lib/ZoneMinder/Trigger/Connection/Example.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Connection/Example.pm], lib/ZoneMinder/Trigger/Channel/Spawning.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Spawning.pm], lib/ZoneMinder/Control.pm=>q[$(INST_LIBDIR)/ZoneMinder/Control.pm], lib/ZoneMinder/General.pm=>q[$(INST_LIBDIR)/ZoneMinder/General.pm], lib/ZoneMinder/Trigger/Channel/Handle.pm=>q[$(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Handle.pm], lib/ZoneMinder/ConfigAdmin.pm=>q[$(INST_LIBDIR)/ZoneMinder/ConfigAdmin.pm] } +# PREREQ_PM => { } +# VERSION_FROM => q[lib/ZoneMinder/Base.pm] + +# --- MakeMaker post_initialize section: + + +# --- MakeMaker const_config section: + +# These definitions are from config.sh (via /usr/lib/perl/5.14/Config.pm). +# They may have been overridden via Makefile.PL or on the command line. +AR = ar +CC = cc +CCCDLFLAGS = -fPIC +CCDLFLAGS = -Wl,-E +DLEXT = so +DLSRC = dl_dlopen.xs +EXE_EXT = +FULL_AR = /usr/bin/ar +LD = cc +LDDLFLAGS = -shared -L/usr/local/lib -fstack-protector +LDFLAGS = -fstack-protector -L/usr/local/lib +LIBC = +LIB_EXT = .a +OBJ_EXT = .o +OSNAME = linux +OSVERS = 2.6.32-5-amd64 +RANLIB = : +SITELIBEXP = /usr/local/share/perl/5.14.2 +SITEARCHEXP = /usr/local/lib/perl/5.14.2 +SO = so +VENDORARCHEXP = /usr/lib/perl5 +VENDORLIBEXP = /usr/share/perl5 + + +# --- MakeMaker constants section: +AR_STATIC_ARGS = cr +DIRFILESEP = / +DFSEP = $(DIRFILESEP) +NAME = ZoneMinder +NAME_SYM = ZoneMinder +VERSION = 1.25.0 +VERSION_MACRO = VERSION +VERSION_SYM = 1_25_0 +DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\" +XS_VERSION = 1.25.0 +XS_VERSION_MACRO = XS_VERSION +XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\" +INST_ARCHLIB = blib/arch +INST_SCRIPT = blib/script +INST_BIN = blib/bin +INST_LIB = blib/lib +INST_MAN1DIR = blib/man1 +INST_MAN3DIR = blib/man3 +MAN1EXT = 1p +MAN3EXT = 3pm +INSTALLDIRS = site +DESTDIR = +PREFIX = /usr +PERLPREFIX = $(PREFIX) +SITEPREFIX = $(PREFIX)/local +VENDORPREFIX = $(PREFIX) +INSTALLPRIVLIB = $(PERLPREFIX)/share/perl/5.14 +DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB) +INSTALLSITELIB = $(SITEPREFIX)/share/perl/5.14.2 +DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB) +INSTALLVENDORLIB = $(VENDORPREFIX)/share/perl5 +DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB) +INSTALLARCHLIB = $(PERLPREFIX)/lib/perl/5.14 +DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB) +INSTALLSITEARCH = $(SITEPREFIX)/lib/perl/5.14.2 +DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH) +INSTALLVENDORARCH = $(VENDORPREFIX)/lib/perl5 +DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH) +INSTALLBIN = $(PERLPREFIX)/bin +DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN) +INSTALLSITEBIN = $(SITEPREFIX)/bin +DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN) +INSTALLVENDORBIN = $(VENDORPREFIX)/bin +DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN) +INSTALLSCRIPT = $(PERLPREFIX)/bin +DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT) +INSTALLSITESCRIPT = $(SITEPREFIX)/bin +DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT) +INSTALLVENDORSCRIPT = $(VENDORPREFIX)/bin +DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT) +INSTALLMAN1DIR = $(PERLPREFIX)/share/man/man1 +DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR) +INSTALLSITEMAN1DIR = $(SITEPREFIX)/man/man1 +DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR) +INSTALLVENDORMAN1DIR = $(VENDORPREFIX)/share/man/man1 +DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR) +INSTALLMAN3DIR = $(PERLPREFIX)/share/man/man3 +DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR) +INSTALLSITEMAN3DIR = $(SITEPREFIX)/man/man3 +DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR) +INSTALLVENDORMAN3DIR = $(VENDORPREFIX)/share/man/man3 +DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR) +PERL_LIB = /usr/share/perl/5.14 +PERL_ARCHLIB = /usr/lib/perl/5.14 +LIBPERL_A = libperl.a +FIRST_MAKEFILE = Makefile +MAKEFILE_OLD = Makefile.old +MAKE_APERL_FILE = Makefile.aperl +PERLMAINCC = $(CC) +PERL_INC = /usr/lib/perl/5.14/CORE +PERL = /usr/bin/perl +FULLPERL = /usr/bin/perl +ABSPERL = $(PERL) +PERLRUN = $(PERL) +FULLPERLRUN = $(FULLPERL) +ABSPERLRUN = $(ABSPERL) +PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)" +PERL_CORE = 0 +PERM_DIR = 755 +PERM_RW = 644 +PERM_RWX = 755 + +MAKEMAKER = /usr/share/perl/5.14/ExtUtils/MakeMaker.pm +MM_VERSION = 6.57_05 +MM_REVISION = 65705 + +# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle). +# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle) +# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar) +# DLBASE = Basename part of dynamic library. May be just equal BASEEXT. +MAKE = make +FULLEXT = ZoneMinder +BASEEXT = ZoneMinder +PARENT_NAME = +DLBASE = $(BASEEXT) +VERSION_FROM = lib/ZoneMinder/Base.pm +OBJECT = +LDFROM = $(OBJECT) +LINKTYPE = dynamic +BOOTDEP = + +# Handy lists of source code files: +XS_FILES = +C_FILES = +O_FILES = +H_FILES = +MAN1PODS = +MAN3PODS = lib/ZoneMinder.pm \ + lib/ZoneMinder/Base.pm \ + lib/ZoneMinder/Config.pm \ + lib/ZoneMinder/ConfigAdmin.pm \ + lib/ZoneMinder/ConfigData.pm \ + lib/ZoneMinder/Control.pm \ + lib/ZoneMinder/Control/AxisV2.pm \ + lib/ZoneMinder/Control/Ncs370.pm \ + lib/ZoneMinder/Control/PanasonicIP.pm \ + lib/ZoneMinder/Control/PelcoD.pm \ + lib/ZoneMinder/Control/Visca.pm \ + lib/ZoneMinder/Control/mjpgStreamer.pm \ + lib/ZoneMinder/Database.pm \ + lib/ZoneMinder/General.pm \ + lib/ZoneMinder/Logger.pm \ + lib/ZoneMinder/Memory.pm \ + lib/ZoneMinder/Trigger/Channel.pm \ + lib/ZoneMinder/Trigger/Channel/File.pm \ + lib/ZoneMinder/Trigger/Channel/Handle.pm \ + lib/ZoneMinder/Trigger/Channel/Inet.pm \ + lib/ZoneMinder/Trigger/Channel/Serial.pm \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + lib/ZoneMinder/Trigger/Channel/Unix.pm \ + lib/ZoneMinder/Trigger/Connection.pm \ + lib/ZoneMinder/Trigger/Connection/Example.pm + +# Where is the Config information that we are using/depend on +CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h + +# Where to build things +INST_LIBDIR = $(INST_LIB) +INST_ARCHLIBDIR = $(INST_ARCHLIB) + +INST_AUTODIR = $(INST_LIB)/auto/$(FULLEXT) +INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT) + +INST_STATIC = +INST_DYNAMIC = +INST_BOOT = + +# Extra linker info +EXPORT_LIST = +PERL_ARCHIVE = +PERL_ARCHIVE_AFTER = + + +TO_INST_PM = lib/ZoneMinder.pm \ + lib/ZoneMinder/Base.pm \ + lib/ZoneMinder/Config.pm \ + lib/ZoneMinder/ConfigAdmin.pm \ + lib/ZoneMinder/ConfigData.pm \ + lib/ZoneMinder/Control.pm \ + lib/ZoneMinder/Control/AxisV2.pm \ + lib/ZoneMinder/Control/Ncs370.pm \ + lib/ZoneMinder/Control/PanasonicIP.pm \ + lib/ZoneMinder/Control/PelcoD.pm \ + lib/ZoneMinder/Control/Visca.pm \ + lib/ZoneMinder/Control/mjpgStreamer.pm \ + lib/ZoneMinder/Database.pm \ + lib/ZoneMinder/General.pm \ + lib/ZoneMinder/Logger.pm \ + lib/ZoneMinder/Memory.pm \ + lib/ZoneMinder/Memory/Mapped.pm \ + lib/ZoneMinder/Memory/Shared.pm \ + lib/ZoneMinder/Trigger/Channel.pm \ + lib/ZoneMinder/Trigger/Channel/File.pm \ + lib/ZoneMinder/Trigger/Channel/Handle.pm \ + lib/ZoneMinder/Trigger/Channel/Inet.pm \ + lib/ZoneMinder/Trigger/Channel/Serial.pm \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + lib/ZoneMinder/Trigger/Channel/Unix.pm \ + lib/ZoneMinder/Trigger/Connection.pm \ + lib/ZoneMinder/Trigger/Connection/Example.pm + +PM_TO_BLIB = lib/ZoneMinder/Trigger/Connection.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Connection.pm \ + lib/ZoneMinder/Control/Ncs370.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/Ncs370.pm \ + lib/ZoneMinder/Trigger/Channel/Serial.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Serial.pm \ + lib/ZoneMinder/Memory/Shared.pm \ + $(INST_LIBDIR)/ZoneMinder/Memory/Shared.pm \ + lib/ZoneMinder.pm \ + $(INST_LIBDIR)/ZoneMinder.pm \ + lib/ZoneMinder/Config.pm \ + $(INST_LIBDIR)/ZoneMinder/Config.pm \ + lib/ZoneMinder/Control/mjpgStreamer.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/mjpgStreamer.pm \ + lib/ZoneMinder/Trigger/Channel/Unix.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Unix.pm \ + lib/ZoneMinder/Control/PanasonicIP.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/PanasonicIP.pm \ + lib/ZoneMinder/Base.pm \ + $(INST_LIBDIR)/ZoneMinder/Base.pm \ + lib/ZoneMinder/Control/AxisV2.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/AxisV2.pm \ + lib/ZoneMinder/Memory/Mapped.pm \ + $(INST_LIBDIR)/ZoneMinder/Memory/Mapped.pm \ + lib/ZoneMinder/Trigger/Channel.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel.pm \ + lib/ZoneMinder/Memory.pm \ + $(INST_LIBDIR)/ZoneMinder/Memory.pm \ + lib/ZoneMinder/Trigger/Channel/File.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/File.pm \ + lib/ZoneMinder/Database.pm \ + $(INST_LIBDIR)/ZoneMinder/Database.pm \ + lib/ZoneMinder/ConfigData.pm \ + $(INST_LIBDIR)/ZoneMinder/ConfigData.pm \ + lib/ZoneMinder/Control/PelcoD.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/PelcoD.pm \ + lib/ZoneMinder/Control/Visca.pm \ + $(INST_LIBDIR)/ZoneMinder/Control/Visca.pm \ + lib/ZoneMinder/Trigger/Channel/Inet.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Inet.pm \ + lib/ZoneMinder/Logger.pm \ + $(INST_LIBDIR)/ZoneMinder/Logger.pm \ + lib/ZoneMinder/Trigger/Connection/Example.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Connection/Example.pm \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Spawning.pm \ + lib/ZoneMinder/Control.pm \ + $(INST_LIBDIR)/ZoneMinder/Control.pm \ + lib/ZoneMinder/General.pm \ + $(INST_LIBDIR)/ZoneMinder/General.pm \ + lib/ZoneMinder/Trigger/Channel/Handle.pm \ + $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Handle.pm \ + lib/ZoneMinder/ConfigAdmin.pm \ + $(INST_LIBDIR)/ZoneMinder/ConfigAdmin.pm + + +# --- MakeMaker platform_constants section: +MM_Unix_VERSION = 6.57_05 +PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc + + +# --- MakeMaker tool_autosplit section: +# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto +AUTOSPLITFILE = $(ABSPERLRUN) -e 'use AutoSplit; autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)' -- + + + +# --- MakeMaker tool_xsubpp section: + + +# --- MakeMaker tools_other section: +SHELL = /bin/sh +CHMOD = chmod +CP = cp +MV = mv +NOOP = $(TRUE) +NOECHO = @ +RM_F = rm -f +RM_RF = rm -rf +TEST_F = test -f +TOUCH = touch +UMASK_NULL = umask 0 +DEV_NULL = > /dev/null 2>&1 +MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' -- +EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' -- +FALSE = false +TRUE = true +ECHO = echo +ECHO_N = echo -n +UNINST = 0 +VERBINST = 0 +MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' -- +DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' -- +UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' -- +WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' -- +MACROSTART = +MACROEND = +USEMAKEFILE = -f +FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' -- + + +# --- MakeMaker makemakerdflt section: +makemakerdflt : all + $(NOECHO) $(NOOP) + + +# --- MakeMaker dist section: +TAR = tar +TARFLAGS = cvf +ZIP = zip +ZIPFLAGS = -r +COMPRESS = gzip --best +SUFFIX = .gz +SHAR = shar +PREOP = $(NOECHO) $(NOOP) +POSTOP = $(NOECHO) $(NOOP) +TO_UNIX = $(NOECHO) $(NOOP) +CI = ci -u +RCS_LABEL = rcs -Nv$(VERSION_SYM): -q +DIST_CP = best +DIST_DEFAULT = tardist +DISTNAME = ZoneMinder +DISTVNAME = ZoneMinder-1.25.0 + + +# --- MakeMaker macro section: + + +# --- MakeMaker depend section: + + +# --- MakeMaker cflags section: + + +# --- MakeMaker const_loadlibs section: + + +# --- MakeMaker const_cccmd section: + + +# --- MakeMaker post_constants section: + + +# --- MakeMaker pasthru section: + +PASTHRU = LIBPERL_A="$(LIBPERL_A)"\ + LINKTYPE="$(LINKTYPE)"\ + LD="$(LD)"\ + PREFIX="$(PREFIX)" + + +# --- MakeMaker special_targets section: +.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT) + +.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir + + + +# --- MakeMaker c_o section: + + +# --- MakeMaker xs_c section: + + +# --- MakeMaker xs_o section: + + +# --- MakeMaker top_targets section: +all :: pure_all manifypods + $(NOECHO) $(NOOP) + + +pure_all :: config pm_to_blib subdirs linkext + $(NOECHO) $(NOOP) + +subdirs :: $(MYEXTLIB) + $(NOECHO) $(NOOP) + +config :: $(FIRST_MAKEFILE) blibdirs + $(NOECHO) $(NOOP) + +help : + perldoc ExtUtils::MakeMaker + + +# --- MakeMaker blibdirs section: +blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists + $(NOECHO) $(NOOP) + +# Backwards compat with 6.18 through 6.25 +blibdirs.ts : blibdirs + $(NOECHO) $(NOOP) + +$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_LIBDIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR) + $(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists + +$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHLIB) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB) + $(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists + +$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_AUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR) + $(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists + +$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR) + $(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists + +$(INST_BIN)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_BIN) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN) + $(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists + +$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_SCRIPT) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT) + $(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists + +$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN1DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR) + $(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists + +$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL + $(NOECHO) $(MKPATH) $(INST_MAN3DIR) + $(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR) + $(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists + + + +# --- MakeMaker linkext section: + +linkext :: $(LINKTYPE) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dlsyms section: + + +# --- MakeMaker dynamic section: + +dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT) + $(NOECHO) $(NOOP) + + +# --- MakeMaker dynamic_bs section: + +BOOTSTRAP = + + +# --- MakeMaker dynamic_lib section: + + +# --- MakeMaker static section: + +## $(INST_PM) has been moved to the all: target. +## It remains here for awhile to allow for old usage: "make static" +static :: $(FIRST_MAKEFILE) $(INST_STATIC) + $(NOECHO) $(NOOP) + + +# --- MakeMaker static_lib section: + + +# --- MakeMaker manifypods section: + +POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--" +POD2MAN = $(POD2MAN_EXE) + + +manifypods : pure_all \ + lib/ZoneMinder/Trigger/Connection.pm \ + lib/ZoneMinder/Control/Ncs370.pm \ + lib/ZoneMinder/Trigger/Channel/Serial.pm \ + lib/ZoneMinder.pm \ + lib/ZoneMinder/Config.pm \ + lib/ZoneMinder/Control/mjpgStreamer.pm \ + lib/ZoneMinder/Control/PanasonicIP.pm \ + lib/ZoneMinder/Base.pm \ + lib/ZoneMinder/Trigger/Channel/Unix.pm \ + lib/ZoneMinder/Control/AxisV2.pm \ + lib/ZoneMinder/Trigger/Channel.pm \ + lib/ZoneMinder/Memory.pm \ + lib/ZoneMinder/Trigger/Channel/File.pm \ + lib/ZoneMinder/Database.pm \ + lib/ZoneMinder/ConfigData.pm \ + lib/ZoneMinder/Control/PelcoD.pm \ + lib/ZoneMinder/Control/Visca.pm \ + lib/ZoneMinder/Trigger/Channel/Inet.pm \ + lib/ZoneMinder/Logger.pm \ + lib/ZoneMinder/Trigger/Connection/Example.pm \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm \ + lib/ZoneMinder/Control.pm \ + lib/ZoneMinder/General.pm \ + lib/ZoneMinder/Trigger/Channel/Handle.pm \ + lib/ZoneMinder/ConfigAdmin.pm + $(NOECHO) $(POD2MAN) --section=$(MAN3EXT) --perm_rw=$(PERM_RW) \ + lib/ZoneMinder/Trigger/Connection.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Connection.$(MAN3EXT) \ + lib/ZoneMinder/Control/Ncs370.pm $(INST_MAN3DIR)/ZoneMinder::Control::Ncs370.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/Serial.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::Serial.$(MAN3EXT) \ + lib/ZoneMinder.pm $(INST_MAN3DIR)/ZoneMinder.$(MAN3EXT) \ + lib/ZoneMinder/Config.pm $(INST_MAN3DIR)/ZoneMinder::Config.$(MAN3EXT) \ + lib/ZoneMinder/Control/mjpgStreamer.pm $(INST_MAN3DIR)/ZoneMinder::Control::mjpgStreamer.$(MAN3EXT) \ + lib/ZoneMinder/Control/PanasonicIP.pm $(INST_MAN3DIR)/ZoneMinder::Control::PanasonicIP.$(MAN3EXT) \ + lib/ZoneMinder/Base.pm $(INST_MAN3DIR)/ZoneMinder::Base.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/Unix.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::Unix.$(MAN3EXT) \ + lib/ZoneMinder/Control/AxisV2.pm $(INST_MAN3DIR)/ZoneMinder::Control::AxisV2.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel.$(MAN3EXT) \ + lib/ZoneMinder/Memory.pm $(INST_MAN3DIR)/ZoneMinder::Memory.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/File.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::File.$(MAN3EXT) \ + lib/ZoneMinder/Database.pm $(INST_MAN3DIR)/ZoneMinder::Database.$(MAN3EXT) \ + lib/ZoneMinder/ConfigData.pm $(INST_MAN3DIR)/ZoneMinder::ConfigData.$(MAN3EXT) \ + lib/ZoneMinder/Control/PelcoD.pm $(INST_MAN3DIR)/ZoneMinder::Control::PelcoD.$(MAN3EXT) \ + lib/ZoneMinder/Control/Visca.pm $(INST_MAN3DIR)/ZoneMinder::Control::Visca.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/Inet.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::Inet.$(MAN3EXT) \ + lib/ZoneMinder/Logger.pm $(INST_MAN3DIR)/ZoneMinder::Logger.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Connection/Example.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Connection::Example.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::Spawning.$(MAN3EXT) \ + lib/ZoneMinder/Control.pm $(INST_MAN3DIR)/ZoneMinder::Control.$(MAN3EXT) \ + lib/ZoneMinder/General.pm $(INST_MAN3DIR)/ZoneMinder::General.$(MAN3EXT) \ + lib/ZoneMinder/Trigger/Channel/Handle.pm $(INST_MAN3DIR)/ZoneMinder::Trigger::Channel::Handle.$(MAN3EXT) \ + lib/ZoneMinder/ConfigAdmin.pm $(INST_MAN3DIR)/ZoneMinder::ConfigAdmin.$(MAN3EXT) + + + + +# --- MakeMaker processPL section: + + +# --- MakeMaker installbin section: + + +# --- MakeMaker subdirs section: + +# none + +# --- MakeMaker clean_subdirs section: +clean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker clean section: + +# Delete temporary files but do not touch installed files. We don't delete +# the Makefile here so a later make realclean still has a makefile to use. + +clean :: clean_subdirs + - $(RM_F) \ + *$(LIB_EXT) core \ + core.[0-9] $(INST_ARCHAUTODIR)/extralibs.all \ + core.[0-9][0-9] $(BASEEXT).bso \ + pm_to_blib.ts core.[0-9][0-9][0-9][0-9] \ + MYMETA.yml $(BASEEXT).x \ + $(BOOTSTRAP) perl$(EXE_EXT) \ + tmon.out *$(OBJ_EXT) \ + pm_to_blib $(INST_ARCHAUTODIR)/extralibs.ld \ + blibdirs.ts core.[0-9][0-9][0-9][0-9][0-9] \ + *perl.core core.*perl.*.? \ + $(MAKE_APERL_FILE) perl \ + $(BASEEXT).def core.[0-9][0-9][0-9] \ + mon.out lib$(BASEEXT).def \ + perlmain.c perl.exe \ + so_locations $(BASEEXT).exp + - $(RM_RF) \ + blib + - $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL) + + +# --- MakeMaker realclean_subdirs section: +realclean_subdirs : + $(NOECHO) $(NOOP) + + +# --- MakeMaker realclean section: +# Delete temporary files (via clean) and also delete dist files +realclean purge :: clean realclean_subdirs + - $(RM_F) \ + $(MAKEFILE_OLD) $(FIRST_MAKEFILE) + - $(RM_RF) \ + $(DISTVNAME) + + +# --- MakeMaker metafile section: +metafile : create_distdir + $(NOECHO) $(ECHO) Generating META.yml + $(NOECHO) $(ECHO) '--- #YAML:1.0' > META_new.yml + $(NOECHO) $(ECHO) 'name: ZoneMinder' >> META_new.yml + $(NOECHO) $(ECHO) 'version: 1.25.0' >> META_new.yml + $(NOECHO) $(ECHO) 'abstract: Container module for common ZoneMinder modules' >> META_new.yml + $(NOECHO) $(ECHO) 'author:' >> META_new.yml + $(NOECHO) $(ECHO) ' - Philip Coombes ' >> META_new.yml + $(NOECHO) $(ECHO) 'license: unknown' >> META_new.yml + $(NOECHO) $(ECHO) 'distribution_type: module' >> META_new.yml + $(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml + $(NOECHO) $(ECHO) ' ExtUtils::MakeMaker: 0' >> META_new.yml + $(NOECHO) $(ECHO) 'requires: {}' >> META_new.yml + $(NOECHO) $(ECHO) 'no_index:' >> META_new.yml + $(NOECHO) $(ECHO) ' directory:' >> META_new.yml + $(NOECHO) $(ECHO) ' - t' >> META_new.yml + $(NOECHO) $(ECHO) ' - inc' >> META_new.yml + $(NOECHO) $(ECHO) 'generated_by: ExtUtils::MakeMaker version 6.57_05' >> META_new.yml + $(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml + $(NOECHO) $(ECHO) ' url: http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml + $(NOECHO) $(ECHO) ' version: 1.4' >> META_new.yml + -$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml + + +# --- MakeMaker signature section: +signature : + cpansign -s + + +# --- MakeMaker dist_basics section: +distclean :: realclean distcheck + $(NOECHO) $(NOOP) + +distcheck : + $(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck + +skipcheck : + $(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck + +manifest : + $(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest + +veryclean : realclean + $(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old + + + +# --- MakeMaker dist_core section: + +dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE) + $(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \ + -e ' if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' -- + +tardist : $(DISTVNAME).tar$(SUFFIX) + $(NOECHO) $(NOOP) + +uutardist : $(DISTVNAME).tar$(SUFFIX) + uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu + +$(DISTVNAME).tar$(SUFFIX) : distdir + $(PREOP) + $(TO_UNIX) + $(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(COMPRESS) $(DISTVNAME).tar + $(POSTOP) + +zipdist : $(DISTVNAME).zip + $(NOECHO) $(NOOP) + +$(DISTVNAME).zip : distdir + $(PREOP) + $(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME) + $(RM_RF) $(DISTVNAME) + $(POSTOP) + +shdist : distdir + $(PREOP) + $(SHAR) $(DISTVNAME) > $(DISTVNAME).shar + $(RM_RF) $(DISTVNAME) + $(POSTOP) + + +# --- MakeMaker distdir section: +create_distdir : + $(RM_RF) $(DISTVNAME) + $(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \ + -e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');" + +distdir : create_distdir distmeta + $(NOECHO) $(NOOP) + + + +# --- MakeMaker dist_test section: +disttest : distdir + cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL + cd $(DISTVNAME) && $(MAKE) $(PASTHRU) + cd $(DISTVNAME) && $(MAKE) test $(PASTHRU) + + + +# --- MakeMaker dist_ci section: + +ci : + $(PERLRUN) "-MExtUtils::Manifest=maniread" \ + -e "@all = keys %{ maniread() };" \ + -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \ + -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});" + + +# --- MakeMaker distmeta section: +distmeta : create_distdir metafile + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add META.yml to MANIFEST: $${'\''@'\''}\n"' -- + + + +# --- MakeMaker distsignature section: +distsignature : create_distdir + $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) } ' \ + -e ' or print "Could not add SIGNATURE to MANIFEST: $${'\''@'\''}\n"' -- + $(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE + cd $(DISTVNAME) && cpansign -s + + + +# --- MakeMaker install section: + +install :: pure_install doc_install + $(NOECHO) $(NOOP) + +install_perl :: pure_perl_install doc_perl_install + $(NOECHO) $(NOOP) + +install_site :: pure_site_install doc_site_install + $(NOECHO) $(NOOP) + +install_vendor :: pure_vendor_install doc_vendor_install + $(NOECHO) $(NOOP) + +pure_install :: pure_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +doc_install :: doc_$(INSTALLDIRS)_install + $(NOECHO) $(NOOP) + +pure__install : pure_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +doc__install : doc_site_install + $(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site + +pure_perl_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLPRIVLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \ + $(INST_BIN) $(DESTINSTALLBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(SITEARCHEXP)/auto/$(FULLEXT) + + +pure_site_install :: all + $(NOECHO) umask 02; $(MOD_INSTALL) \ + read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \ + write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \ + $(INST_LIB) $(DESTINSTALLSITELIB) \ + $(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \ + $(INST_BIN) $(DESTINSTALLSITEBIN) \ + $(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR) + $(NOECHO) $(WARN_IF_OLD_PACKLIST) \ + $(PERL_ARCHLIB)/auto/$(FULLEXT) + +pure_vendor_install :: all + $(NOECHO) umask 022; $(MOD_INSTALL) \ + $(INST_LIB) $(DESTINSTALLVENDORLIB) \ + $(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \ + $(INST_BIN) $(DESTINSTALLVENDORBIN) \ + $(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \ + $(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \ + $(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR) + +doc_perl_install :: all + +doc_site_install :: all + $(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLSITEARCH)/perllocal.pod + -$(NOECHO) umask 02; $(MKPATH) $(DESTINSTALLSITEARCH) + -$(NOECHO) umask 02; $(DOC_INSTALL) \ + "Module" "$(NAME)" \ + "installed into" "$(INSTALLSITELIB)" \ + LINKTYPE "$(LINKTYPE)" \ + VERSION "$(VERSION)" \ + EXE_FILES "$(EXE_FILES)" \ + >> $(DESTINSTALLSITEARCH)/perllocal.pod + +doc_vendor_install :: all + + +uninstall :: uninstall_from_$(INSTALLDIRS)dirs + $(NOECHO) $(NOOP) + +uninstall_from_perldirs :: + +uninstall_from_sitedirs :: + $(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist + +uninstall_from_vendordirs :: + + + +# --- MakeMaker force section: +# Phony target to force checking subdirectories. +FORCE : + $(NOECHO) $(NOOP) + + +# --- MakeMaker perldepend section: + + +# --- MakeMaker makefile section: +# We take a very conservative approach here, but it's worth it. +# We move Makefile to Makefile.old here to avoid gnu make looping. +$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP) + $(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?" + $(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..." + -$(NOECHO) $(RM_F) $(MAKEFILE_OLD) + -$(NOECHO) $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) + - $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL) + $(PERLRUN) Makefile.PL + $(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <==" + $(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command. <==" + $(FALSE) + + + +# --- MakeMaker staticmake section: + +# --- MakeMaker makeaperl section --- +MAP_TARGET = perl +FULLPERL = /usr/bin/perl + +$(MAP_TARGET) :: static $(MAKE_APERL_FILE) + $(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@ + +$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib + $(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET) + $(NOECHO) $(PERLRUNINST) \ + Makefile.PL DIR= \ + MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \ + MAKEAPERL=1 NORECURS=1 CCCDLFLAGS= + + +# --- MakeMaker test section: + +TEST_VERBOSE=0 +TEST_TYPE=test_$(LINKTYPE) +TEST_FILE = test.pl +TEST_FILES = t/*.t +TESTDB_SW = -d + +testdb :: testdb_$(LINKTYPE) + +test :: $(TEST_TYPE) subdirs-test + +subdirs-test :: + $(NOECHO) $(NOOP) + + +test_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES) + +testdb_dynamic :: pure_all + PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE) + +test_ : test_dynamic + +test_static :: test_dynamic +testdb_static :: testdb_dynamic + + +# --- MakeMaker ppd section: +# Creates a PPD (Perl Package Description) for a binary distribution. +ppd : + $(NOECHO) $(ECHO) '' > $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Container module for common ZoneMinder modules' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' Philip Coombes <philip.coombes@zoneminder.com>' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) ' ' >> $(DISTNAME).ppd + $(NOECHO) $(ECHO) '' >> $(DISTNAME).ppd + + +# --- MakeMaker pm_to_blib section: + +pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM) + $(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \ + lib/ZoneMinder/Trigger/Connection.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Connection.pm \ + lib/ZoneMinder/Control/Ncs370.pm $(INST_LIBDIR)/ZoneMinder/Control/Ncs370.pm \ + lib/ZoneMinder/Trigger/Channel/Serial.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Serial.pm \ + lib/ZoneMinder/Memory/Shared.pm $(INST_LIBDIR)/ZoneMinder/Memory/Shared.pm \ + lib/ZoneMinder.pm $(INST_LIBDIR)/ZoneMinder.pm \ + lib/ZoneMinder/Config.pm $(INST_LIBDIR)/ZoneMinder/Config.pm \ + lib/ZoneMinder/Control/mjpgStreamer.pm $(INST_LIBDIR)/ZoneMinder/Control/mjpgStreamer.pm \ + lib/ZoneMinder/Trigger/Channel/Unix.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Unix.pm \ + lib/ZoneMinder/Control/PanasonicIP.pm $(INST_LIBDIR)/ZoneMinder/Control/PanasonicIP.pm \ + lib/ZoneMinder/Base.pm $(INST_LIBDIR)/ZoneMinder/Base.pm \ + lib/ZoneMinder/Control/AxisV2.pm $(INST_LIBDIR)/ZoneMinder/Control/AxisV2.pm \ + lib/ZoneMinder/Memory/Mapped.pm $(INST_LIBDIR)/ZoneMinder/Memory/Mapped.pm \ + lib/ZoneMinder/Trigger/Channel.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel.pm \ + lib/ZoneMinder/Memory.pm $(INST_LIBDIR)/ZoneMinder/Memory.pm \ + lib/ZoneMinder/Trigger/Channel/File.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/File.pm \ + lib/ZoneMinder/Database.pm $(INST_LIBDIR)/ZoneMinder/Database.pm \ + lib/ZoneMinder/ConfigData.pm $(INST_LIBDIR)/ZoneMinder/ConfigData.pm \ + lib/ZoneMinder/Control/PelcoD.pm $(INST_LIBDIR)/ZoneMinder/Control/PelcoD.pm \ + lib/ZoneMinder/Control/Visca.pm $(INST_LIBDIR)/ZoneMinder/Control/Visca.pm \ + lib/ZoneMinder/Trigger/Channel/Inet.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Inet.pm \ + lib/ZoneMinder/Logger.pm $(INST_LIBDIR)/ZoneMinder/Logger.pm \ + lib/ZoneMinder/Trigger/Connection/Example.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Connection/Example.pm \ + lib/ZoneMinder/Trigger/Channel/Spawning.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Spawning.pm \ + lib/ZoneMinder/Control.pm $(INST_LIBDIR)/ZoneMinder/Control.pm \ + lib/ZoneMinder/General.pm $(INST_LIBDIR)/ZoneMinder/General.pm \ + lib/ZoneMinder/Trigger/Channel/Handle.pm $(INST_LIBDIR)/ZoneMinder/Trigger/Channel/Handle.pm \ + lib/ZoneMinder/ConfigAdmin.pm $(INST_LIBDIR)/ZoneMinder/ConfigAdmin.pm + $(NOECHO) $(TOUCH) pm_to_blib + + +# --- MakeMaker selfdocument section: + + +# --- MakeMaker postamble section: + + +# End. diff --git a/scripts/ZoneMinder/README b/scripts/ZoneMinder/README new file mode 100644 index 000000000..fd005204c --- /dev/null +++ b/scripts/ZoneMinder/README @@ -0,0 +1,40 @@ +ZoneMinder version 0.01 +======================= + +The README is used to introduce the module and provide instructions on +how to install the module, any machine dependencies it may have (for +example C compilers and installed libraries) and any other information +that should be provided before the module is installed. + +A README file is required for CPAN modules since CPAN extracts the +README file from a module distribution so that people browsing the +archive can use it get an idea of the modules uses. It is usually a +good idea to provide version information here so that people can +decide whether fixes for the module are worth downloading. + +INSTALLATION + +To install this module type the following: + + perl Makefile.PL + make + make test + make install + +DEPENDENCIES + +This module requires these other modules and libraries: + + blah blah blah + +COPYRIGHT AND LICENCE + +Put the correct copyright and licence information here. + +Copyright (C) 2005 by 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. + + diff --git a/scripts/ZoneMinder/blib/arch/.exists b/scripts/ZoneMinder/blib/arch/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/arch/auto/ZoneMinder/.exists b/scripts/ZoneMinder/blib/arch/auto/ZoneMinder/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/bin/.exists b/scripts/ZoneMinder/blib/bin/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/lib/.exists b/scripts/ZoneMinder/blib/lib/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder.pm new file mode 100644 index 000000000..41c972650 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder.pm @@ -0,0 +1,130 @@ +# ========================================================================== +# +# ZoneMinder Common 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; + +use 5.006; +use strict; +use warnings; + +require Exporter; +use ZoneMinder::Base qw(:all); +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); +use ZoneMinder::General qw(:all); +use ZoneMinder::Database qw(:all); +use ZoneMinder::Memory qw(:all); + +our @ISA = qw(Exporter ZoneMinder::Base ZoneMinder::Config ZoneMinder::Logger ZoneMinder::General ZoneMinder::Database ZoneMinder::Memory); + +# 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 = ( + 'base' => [ + @ZoneMinder::Base::EXPORT_OK + ], + 'config' => [ + @ZoneMinder::Config::EXPORT_OK + ], + 'debug' => [ + @ZoneMinder::Logger::EXPORT_OK + ], + 'general' => [ + @ZoneMinder::General::EXPORT_OK + ], + 'database' => [ + @ZoneMinder::Database::EXPORT_OK + ], + 'memory' => [ + @ZoneMinder::Memory::EXPORT_OK + ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = @{ $EXPORT_TAGS{'all'} }; + +our @EXPORT = ( @EXPORT_OK ); + +our $VERSION = $ZoneMinder::Base::VERSION; + +1; +__END__ + +=head1 NAME + +ZoneMinder - Container module for common ZoneMinder modules + +=head1 SYNOPSIS + + use ZoneMinder; + +=head1 DESCRIPTION + +This module is a convenience container module that uses the +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database and ZoneMinder::Memory modules. It also +exports by default all symbols provided by the 'all' tag of +each of the modules. + +Thus 'use'ing this module is equivalent to the following + + use ZoneMinder::Base qw(:all); + use ZoneMinder::Config qw(:all); + use ZoneMinder::Logger qw(:all); + use ZoneMinder::Database qw(:all); + use ZoneMinder::Memory qw(:all); + +but is somewhat easier. + +=head2 EXPORT + +All symbols exported by the 'all' tag of each of the included +modules. + +=head1 SEE ALSO + +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database, ZoneMinder::Memory + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005 by 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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Base.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Base.pm new file mode 100644 index 000000000..095ddc37b --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Base.pm @@ -0,0 +1,86 @@ +# ========================================================================== +# +# ZoneMinder Base 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::Base; + +use 5.006; +use strict; +use warnings; + +require Exporter; + +our @ISA = qw(Exporter); + +# 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 = ( 'all' => [ qw() ] ); + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = "1.25.0"; + +1; +__END__ + +=head1 NAME + +ZoneMinder::Base - Base perl module for ZoneMinder + +=head1 SYNOPSIS + + use ZoneMinder::Base; + +=head1 DESCRIPTION + +This module is the base module for the rest of the ZoneMinder modules. It is included by each of the other modules but serves no purpose other than to propagate the perl module version amongst the other modules. You will never need to use this module directly but if you write new ZoneMinder modules they should include it. + +=head2 EXPORT + +None by default. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Config.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Config.pm new file mode 100644 index 000000000..e447f86f9 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Config.pm @@ -0,0 +1,145 @@ +# ========================================================================== +# +# ZoneMinder Config 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::Config; + +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_CONFIG; # Get populated by BEGIN + +our %EXPORT_TAGS = ( + 'constants' => [ qw( + ZM_PID + ) ] +); +push( @{$EXPORT_TAGS{config}}, @EXPORT_CONFIG ); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +use constant ZM_PID => "/var/run/zm/zm.pid"; # Path to the ZoneMinder run pid file +use constant ZM_CONFIG => "/etc/zm/zm.conf"; # Path to the ZoneMinder config file + +use Carp; + +# Load the config from the database into the symbol table +BEGIN +{ + no strict 'refs'; + + my $config_file = ZM_CONFIG; + ( my $local_config_file = $config_file ) =~ s|^.*/|./|; + if ( -s $local_config_file && -r $local_config_file ) + { + print( STDERR "Warning, overriding installed $local_config_file file with local copy\n" ); + $config_file = $local_config_file; + } + open( CONFIG, "<".$config_file ) or croak( "Can't open config file '$config_file': $!" ); + foreach my $str ( ) + { + next if ( $str =~ /^\s*$/ ); + next if ( $str =~ /^\s*#/ ); + my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.+?)\s*$/; + $name =~ tr/a-z/A-Z/; + *{$name} = sub { $value }; + push( @EXPORT_CONFIG, $name ); + } + close( CONFIG ); + + use DBI; + my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_HOST, &ZM_DB_USER, &ZM_DB_PASS ); + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + while( my $config = $sth->fetchrow_hashref() ) + { + *{$config->{Name}} = sub { $config->{Value} }; + push( @EXPORT_CONFIG, $config->{Name} ); + } + $sth->finish(); + $dbh->disconnect(); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::Config - ZoneMinder configuration module. + +=head1 SYNOPSIS + + use ZoneMinder::Config qw(:all); + +=head1 DESCRIPTION + +The ZoneMinder::Config module is used to import the ZoneMinder configuration from the database. It will do this at compile time in a BEGIN block and require access to the zm.conf file either in the current directory or in its defined location in order to determine database access details, configuration from this file will also be included. If the :all or :config tags are used then this configuration is exported into the namespace of the calling program or module. + +Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. + + $lang = ZM_LANG_DEFAULT; + +=head2 EXPORT + +None by default. +The :constants tag will export the ZM_PID constant which details the location of the zm.pid file +The :config tag will export all configuration from the database as well as any from the zm.conf file +The :all tag will export all above symbols. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigAdmin.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigAdmin.pm new file mode 100644 index 000000000..8ee1ec82b --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigAdmin.pm @@ -0,0 +1,213 @@ +# ========================================================================== +# +# ZoneMinder Config Admin 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigAdmin; + +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( + loadConfigFromDB + saveConfigToDB + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'functions'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Administration +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::ConfigData qw(:all); + +use Carp; + +sub loadConfigFromDB +{ + print( "Loading config from DB\n" ); + my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + + if ( !$dbh ) + { + print( "Error: unable to load options from database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + my $option_count = 0; + while( my $config = $sth->fetchrow_hashref() ) + { + my ( $name, $value ) = ( $config->{Name}, $config->{Value} ); + #print( "Name = '$name'\n" ); + my $option = $options_hash{$name}; + if ( !$option ) + { + warn( "No option '$name' found, removing" ); + next; + } + #next if ( $option->{category} eq 'hidden' ); + if ( defined($value) ) + { + if ( $option->{type} == $types{boolean} ) + { + $option->{value} = $value?"yes":"no"; + } + else + { + $option->{value} = $value; + } + } + $option_count++;; + } + $sth->finish(); + $dbh->disconnect(); + return( $option_count ); +} + +sub saveConfigToDB +{ + print( "Saving config to DB\n" ); + my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + + if ( !$dbh ) + { + print( "Error: unable to save options to database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "delete from Config"; + my $res = $dbh->do( $sql ) or croak( "Can't do '$sql': ".$dbh->errstr() ); + + $sql = "replace into Config set Id = ?, Name = ?, Value = ?, Type = ?, DefaultValue = ?, Hint = ?, Pattern = ?, Format = ?, Prompt = ?, Help = ?, Category = ?, Readonly = ?, Requires = ?"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $option ( @options ) + { + #next if ( $option->{category} eq 'hidden' ); + #print( $option->{name}."\n" ) if ( !$option->{category} ); + $option->{db_type} = $option->{type}->{db_type}; + $option->{db_hint} = $option->{type}->{hint}; + $option->{db_pattern} = $option->{type}->{pattern}; + $option->{db_format} = $option->{type}->{format}; + if ( $option->{db_type} eq "boolean" ) + { + $option->{db_value} = ($option->{value} eq "yes")?"1":"0"; + } + else + { + $option->{db_value} = $option->{value}; + } + if ( my $requires = $option->{requires} ) + { + $option->{db_requires} = join( ";", map { my $value = $_->{value}; $value = ($value eq "yes")?1:0 if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ); ( "$_->{name}=$value" ) } @$requires ); + } + else + { + } + my $res = $sth->execute( $option->{id}, $option->{name}, $option->{db_value}, $option->{db_type}, $option->{default}, $option->{db_hint}, $option->{db_pattern}, $option->{db_format}, $option->{description}, $option->{help}, $option->{category}, $option->{readonly}?1:0, $option->{db_requires} ) or croak( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + $dbh->disconnect(); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigAdmin - ZoneMinder Configuration Administration module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigAdmin; + use ZoneMinder::ConfigAdmin qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigAdmin module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigData.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigData.pm new file mode 100644 index 000000000..e108d8687 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/ConfigData.pm @@ -0,0 +1,2056 @@ +# ========================================================================== +# +# ZoneMinder Config Data Module, $Date: 2011-01-20 18:49:42 +0000 (Thu, 20 Jan 2011) $, $Revision: 3230 $ +# 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigData; + +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 = ( + 'data' => [ qw( + %types + @options + %options_hash + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'data'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Data +# +# ========================================================================== + +use Carp; + +our $configInitialised = 0; + +sub INIT +{ + initialiseConfig(); +} + +# Types +our %types = +( + string => { db_type=>"string", hint=>"string", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + alphanum => { db_type=>"string", hint=>"alphanumeric", pattern=>qr|^([a-zA-Z0-9-_]+)$|, format=>q( $1 ) }, + text => { db_type=>"text", hint=>"free text", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + boolean => { db_type=>"boolean", hint=>"yes|no", pattern=>qr|^([yn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : "no" ) }, + integer => { db_type=>"integer", hint=>"integer", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + decimal => { db_type=>"decimal", hint=>"decimal", pattern=>qr|^(\d+(?:\.\d+)?)$|, format=>q( $1 ) }, + hexadecimal => { db_type=>"hexadecimal", hint=>"hexadecimal", pattern=>qr|^(?:0x)?([0-9a-f]{1,8})$|, format=>q( "0x".$1 ) }, + tristate => { db_type=>"string", hint=>"auto|yes|no", pattern=>qr|^([ayn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : ($1 =~ /^n/ ? "no" : "auto" ) ) }, + abs_path => { db_type=>"string", hint=>"/absolute/path/to/somewhere", pattern=>qr|^((?:/[^/]*)+?)/?$|, format=>q( $1 ) }, + rel_path => { db_type=>"string", hint=>"relative/path/to/somewhere", pattern=>qr|^((?:[^/].*)?)/?$|, format=>q( $1 ) }, + directory => { db_type=>"string", hint=>"directory", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + file => { db_type=>"string", hint=>"filename", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + hostname => { db_type=>"string", hint=>"host.your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)$|, format=>q( $1 ) }, + url => { db_type=>"string", hint=>"http://host.your.domain/", pattern=>qr|^(?:http://)?(.+)$|, format=>q( "http://".$1 ) }, + email => { db_type=>"string", hint=>"your.name\@your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$|, format=>q( $1\@$2 ) }, +); + +our @options = +( + { + name => "ZM_LANG_DEFAULT", + default => "en_gb", + description => "Default language used by web interface", + help => "ZoneMinder allows the web interface to use languages other than English if the appropriate language file has been created and is present. This option allows you to change the default language that is used from the shipped language, British English, to another language", + type => $types{string}, + category => "system", + }, + { + name => "ZM_OPT_USE_AUTH", + default => "no", + description => "Authenticate user logins to ZoneMinder", + help => "ZoneMinder can run in two modes. The simplest is an entirely unauthenticated mode where anyone can access ZoneMinder and perform all tasks. This is most suitable for installations where the web server access is limited in other ways. The other mode enables user accounts with varying sets of permissions. Users must login or authenticate to access ZoneMinder and are limited by their defined permissions.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_TYPE", + default => "builtin", + description => "What is used to authenticate ZoneMinder users", + help => "ZoneMinder can use two methods to authenticate users when running in authenticated mode. The first is a builtin method where ZoneMinder provides facilities for users to log in and maintains track of their identity. The second method allows interworking with other methods such as http basic authentication which passes an independently authentication 'remote' user via http. In this case ZoneMinder would use the supplied user without additional authentication provided such a user is configured ion ZoneMinder.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"builtin|remote", pattern=>qr|^([br])|i, format=>q( $1 =~ /^b/ ? "builtin" : "remote" ) }, + category => "system", + }, + { + name => "ZM_AUTH_RELAY", + default => "hashed", + description => "Method used to relay authentication information", + help => "When ZoneMinder is running in authenticated mode it can pass user details between the web pages and the back end processes. There are two methods for doing this. This first is to use a time limited hashed string which contains no direct username or password details, the second method is to pass the username and passwords around in plaintext. This method is not recommend except where you do not have the md5 libraries available on your system or you have a completely isolated system with no external access. You can also switch off authentication relaying if your system is isolated in other ways.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"hashed|plain|none", pattern=>qr|^([hpn])|i, format=>q( ($1 =~ /^h/) ? "hashed" : ($1 =~ /^p/ ? "plain" : "none" ) ) }, + category => "system", + }, + { + name => "ZM_AUTH_HASH_SECRET", + default => "...Change me to something unique...", + description => "Secret for encoding hashed authentication information", + help => "When ZoneMinder is running in hashed authenticated mode it is necessary to generate hashed strings containing encrypted sensitive information such as usernames and password. Although these string are reasonably secure the addition of a random secret increases security substantially.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{string}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_IPS", + default => "yes", + description => "Include IP addresses in the authentication hash", + help => "When ZoneMinder is running in hashed authenticated mode it can optionally include the requesting IP address in the resultant hash. This adds an extra level of security as only requests from that address may use that authentication key. However in some circumstances, such as access over mobile networks, the requesting address can change for each request which will cause most requests to fail. This option allows you to control whether IP addresses are included in the authentication hash on your system. If you experience intermitent problems with authentication, switching this option off may help.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_LOGINS", + default => "no", + description => "Allow login by authentication hash", + help => "The normal process for logging into ZoneMinder is via the login screen with username and password. In some circumstances it may be desirable to allow access directly to one or more pages, for instance from a third party application. If this option is enabled then adding an 'auth' parameter to any request will include a shortcut login bypassing the login screen, if not already logged in. As authentication hashes are time and, optionally, IP limited this can allow short-term access to ZoneMinder screens from other web pages etc. In order to use this the calling application will hae to generate the authentication hash itself and ensure it is valid. If you use this option you should ensure that you have modified the ZM_AUTH_HASH_SECRET to somethign unique to your system.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_DIR_EVENTS", + default => "events", + description => "Directory where events are stored", + help => "This is the path to the events directory where all the event images and other miscellaneous files are stored. It is normally given as a subdirectory of the web directory you have specified earlier however if disk space is tight it can reside on another partition in which case you should create a link from that area to the path you give here.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_USE_DEEP_STORAGE", + default => "yes", + description => "Use a deep filesystem hierarchy for events", + help => "Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date.", + type => $types{boolean}, + category => "paths", + }, + { + name => "ZM_DIR_IMAGES", + default => "images", + description => "Directory where the images that the ZoneMinder client generates are stored", + help => "ZoneMinder generates a myriad of images, mosty of which are associated with events. For those that aren't this is where they go.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_DIR_SOUNDS", + default => "sounds", + description => "Directory to the sounds that the ZoneMinder client can use", + help => "ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where (relative to the web root) to look for this file.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_PATH_ZMS", + default => "/cgi-bin/nph-zms", + description => "Web path to zms streaming server", + help => "The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing 'zms' to 'nph-zms'.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_COLOUR_JPEG_FILES", + default => "yes", + description => "Colourise greyscale JPEG files", + help => "Cameras that capture in greyscale can write their captured images to jpeg files with a corresponding greyscale colour space. This saves a small amount of disk space over colour ones. However some tools such as ffmpeg either fail to work with this colour space or have to convert it beforehand. Setting this option to yes uses up a little more space but makes creation of MPEG files much faster.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_ADD_JPEG_COMMENTS", + default => "no", + description => "Add jpeg timestamp annotations as file header comments", + help => "JPEG files may have a number of extra fields added to the file header. The comment field may have any kind of text added. This options allows you to have the same text that is used to annotate the image additionally included as a file header comment. If you archive event images to other locations this may help you locate images for particular events or times if you use software that can read comment headers.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_JPEG_FILE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the saved event files (1-100)", + help => "When ZoneMinder detects an event it will save the images associated with that event to files. These files are in the JPEG format and can be viewed or streamed later. This option specifies what image quality should be used to save these files. A higher number means better quality but less compression so will take up more disk space and take longer to view over a slow connection. By contrast a low number means smaller, quicker to view, files but at the price of lower quality images. This setting applies to all images written except if the capture image has caused an alarm and the alarm file quality option is set at a higher value when that is used instead.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_JPEG_ALARM_FILE_QUALITY", + default => "0", + description => "Set the JPEG quality setting for the saved event files during an alarm (1-100)", + help => "This value is equivalent to the regular jpeg file quality setting above except that it only applies to images saved while in an alarm state and then only if this value is set to a higher quality setting than the ordinary file setting. If set to a lower value then it is ignored. Thus leaving it at the default of 0 effectively means to use the regular file quality setting for all saved images. This is to prevent acccidentally saving important images at a worse quality setting.", + type => $types{integer}, + category => "images", + }, + # Deprecated, now stream quality + { + name => "ZM_JPEG_IMAGE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_JPEG_STREAM_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_MPEG_TIMED_FRAMES", + default => "yes", + description => "Tag video frames with a timestamp for more realistic streaming", + help => "When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it's capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it's 'real' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_MPEG_LIVE_FORMAT", + default => "swf", + description => "What format 'live' video streams are played in", + help => "When using MPEG mode ZoneMinder can output live video. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player but I'm currently not sure what, if anything, works on a Linux platform. If you find out please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_MPEG_REPLAY_FORMAT", + default => "swf", + description => "What format 'replay' video streams are played in", + help => "When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player and 'mpg', or 'avi' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_RAND_STREAM", + default => "yes", + description => "Add a random string to prevent caching of streams", + help => "Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_OPT_CAMBOZOLA", + default => "no", + description => "Is the (optional) cambozola java streaming client installed", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_CAMBOZOLA", + default => "cambozola.jar", + description => "Web path to (optional) cambozola java streaming client", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. Leave this as 'cambozola.jar' if cambozola is installed in the same directory as the ZoneMinder web client files.", + requires => [ { name=>"ZM_OPT_CAMBOZOLA", value=>"yes" } ], + type => $types{rel_path}, + category => "images", + }, + { + name => "ZM_RELOAD_CAMBOZOLA", + default => "0", + description => "After how many seconds should Cambozola be reloaded in live view", + help => "Cambozola allows for the viewing of streaming MJPEG however it caches the entire stream into cache space on the computer, setting this to a number > 0 will cause it to automatically reload after that many seconds to avoid filling up a hard drive.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_TIMESTAMP_ON_CAPTURE", + default => "yes", + description => "Timestamp images as soon as they are captured", + help => "ZoneMinder can add a timestamp to images in two ways. The default method, when this option is set, is that each image is timestamped immediately when captured and so the image held in memory is marked right away. The second method does not timestamp the images until they are either saved as part of an event or accessed over the web. The timestamp used in both methods will contain the same time as this is preserved along with the image. The first method ensures that an image is timestamped regardless of any other circumstances but will result in all images being timestamped even those never saved or viewed. The second method necessitates that saved images are copied before being saved otherwise two timestamps perhaps at different scales may be applied. This has the (perhaps) desirable side effect that the timestamp is always applied at the same resolution so an image that has scaling applied will still have a legible and correctly scaled timestamp.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CPU_EXTENSIONS", + default => "yes", + description => "Use advanced CPU extensions to increase performance", + help => "When advanced processor extensions such as SSE2 or SSSE3 are available, ZoneMinder can use them, which should increase performance and reduce system load. Enabling this option on processors that do not support the advanced processors extensions used by ZoneMinder is harmless and will have no effect.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_FAST_IMAGE_BLENDS", + default => "yes", + description => "Use a fast algorithm to blend the reference image", + help => "To detect alarms ZoneMinder needs to blend the captured image with the stored reference image to update it for comparison with the next image. The reference blend percentage specified for the monitor controls how much the new image affects the reference image. There are two methods that are available for this. If this option is set then fast calculation which does not use any multiplication or division is used. This calculation is extremely fast, however it limits the possible blend percentages to 50%, 25%, 12.5%, 6.25%, 3.25% and 1.5%. Any other blend percentage will be rounded to the nearest possible one. The alternative is to switch this option off and use standard blending instead, which is slower.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_ADAPTIVE_SKIP", + default => "yes", + description => "Should frame analysis try and be efficient in skipping frames", + help => "In previous versions of ZoneMinder the analysis daemon would attempt to keep up with the capture daemon by processing the last captured frame on each pass. This would sometimes have the undesirable side-effect of missing a chunk of the initial activity that caused the alarm because the pre-alarm frames would all have to be written to disk and the database before processing the next frame, leading to some delay between the first and second event frames. Setting this option enables a newer adaptive algorithm where the analysis daemon attempts to process as many captured frames as possible, only skipping frames when in danger of the capture daemon overwriting yet to be processed frames. This skip is variable depending on the size of the ring buffer and the amount of space left in it. Enabling this option will give you much better coverage of the beginning of alarms whilst biasing out any skipped frames towards the middle or end of the event. However you should be aware that this will have the effect of making the analysis daemon run somewhat behind the capture daemon during events and for particularly fast rates of capture it is possible for the adaptive algorithm to be overwhelmed and not have time to react to a rapid build up of pending frames and thus for a buffer overrun condition to occur.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_BLEND_ALARMED_IMAGES", + default => "yes", + description => "Blend alarmed images to update the reference image", + help => "To detect alarms ZoneMinder compares an image with a reference image which is formed from a composite of the previous images. This option determines whether images that cause events are included in this process. Doing so may increase the precision of the alarmed region but can cause problems if wholescale lighting changes cause alarms as this would not get fed back into the image and an alarm may persist indefinately. A better way to achive the same effect in most cases is to lower substantially the reference blend percentage in specific monitors.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_MAX_SUSPEND_TIME", + default => "30", + description => "Maximum time that a monitor may have motion detection suspended", + help => "ZoneMinder allows monitors to have motion detection to be suspended, for instance while panning a camera. Ordinarily this relies on the operator resuming motion detection afterwards as failure to do so can leave a monitor in a permanently suspended state. This setting allows you to set a maximum time which a camera may be suspended for before it automatically resumes motion detection. This time can be extended by subsequent suspend indications after the first so continuous camera movement will also occur while the monitor is suspended.", + type => $types{integer}, + category => "config", + }, + # Deprecated, really no longer necessary + { + name => "ZM_OPT_REMOTE_CAMERAS", + default => "no", + description => "Are you going to use remote/networked cameras", + help => "ZoneMinder can work with both local cameras, ie. those attached physically to your computer and remote or network cameras. If you will be using networked cameras select this option.", + type => $types{boolean}, + category => "hidden", + }, + # Deprecated, now set on a per monitor basis using the Method field + { + name => "ZM_NETCAM_REGEXPS", + default => "yes", + description => "Use regular expression matching with network cameras", + help => "Traditionally ZoneMinder has used complex regular regular expressions to handle the multitude of formats that network cameras produce. In versions from 1.21.1 the default is to use a simpler and faster built in pattern matching methodology. This works well with most networks cameras but if you have problems you can try the older, but more flexible, regular expression based method by selecting this option. Note, to use this method you must have libpcre installed on your system.", + requires => [ { name => "ZM_OPT_REMOTE_CAMERAS", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_HTTP_VERSION", + default => "1.1", + description => "The version of HTTP that ZoneMinder will use to connect", + help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.", + type => { db_type=>"string", hint=>"1.1|1.0", pattern=>qr|^(1\.[01])$|, format=>q( $1?$1:"" ) }, + category => "network", + }, + { + name => "ZM_HTTP_UA", + default => "ZoneMinder", + description => "The user agent that ZoneMinder uses to identify itself", + help => "When ZoneMinder communicates with remote cameras it will identify itself using this string and it's version number. This is normally sufficient, however if a particular cameras expects only to communicate with certain browsers then this can be changed to a different string identifying ZoneMinder as Internet Explorer or Netscape etc.", + type => $types{string}, + category => "network", + }, + { + name => "ZM_HTTP_TIMEOUT", + default => "2500", + description => "How long ZoneMinder waits before giving up on images (milliseconds)", + help => "When retrieving remote images ZoneMinder will wait for this length of time before deciding that an image is not going to arrive and taking steps to retry. This timeout is in milliseconds (1000 per second) and will apply to each part of an image if it is not sent in one whole chunk.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MIN_RTP_PORT", + default => "40200", + description => "Minimum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the minimum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MAX_RTP_PORT", + default => "40499", + description => "Maximum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the maximum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting. You should also ensure that you have opened up at least two ports for each monitor that will be connecting to unicasting network cameras.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_OPT_FFMPEG", + default => "yes", + description => "Is the ffmpeg video encoder/decoder installed", + help => "ZoneMinder can optionally encode a series of video images into an MPEG encoded movie file for viewing, downloading or storage. This option allows you to specify whether you have the ffmpeg tools installed. Note that creating MPEG files can be fairly CPU and disk intensive and is not a required option as events can still be reviewed as video streams without it.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_FFMPEG", + default => "/usr/bin/ffmpeg", + description => "Path to (optional) ffmpeg mpeg encoder", + help => "This path should point to where ffmpeg has been installed.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{abs_path}, + category => "images", + }, + { + name => "ZM_FFMPEG_INPUT_OPTIONS", + default => "", + description => "Additional input options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before the -i option). Check the ffmpeg documentation for a full list of options which may be used here.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_OUTPUT_OPTIONS", + default => "-r 25", + description => "Additional output options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after the -i option). Check the ffmpeg documentation for a full list of options which may be used here. The most common one will often be to force an output frame rate supported by the video encoder.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_FORMATS", + default => "mpg mpeg wmv asf avi* mov swf 3gp**", + description => "Formats to allow for ffmpeg video generation", + help => "Ffmpeg can generate video in many different formats. This option allows you to list the ones you want to be able to select. As new formats are supported by ffmpeg you can add them here and be able to use them immediately. Adding a '*' after a format indicates that this will be the default format used for web video, adding '**' defines the default format for phone video.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_LOG_LEVEL_SYSLOG", + default => "0", + description => "Save logging output to the system log", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_FILE", + default => "-5", + description => "Save logging output to component files", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_WEBLOG", + default => "-5", + description => "Save logging output to the weblog", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_DATABASE", + default => "0", + description => "Save logging output to the database", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DATABASE_LIMIT", + default => "7 day", + description => "Maximum number of log entries to retain", + help => "If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as ' day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.", + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG", + default => "no", + description => "Switch debugging on", + help => "ZoneMinder components usually support debug logging available to help with diagnosing problems. Binary components have several levels of debug whereas more other components have only one. Normally this is disabled to minimise performance penalties and avoid filling logs too quickly. This option lets you switch on other options that allow you to configure additional debug information to be output. Components will pick up this instruction when they are restarted.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_TARGET", + default => "", + description => "What components should have extra debug enabled", + help => "There are three scopes of debug available. Leaving this option blank means that all components will use extra debug (not recommended). Setting this option to '_', e.g. _zmc, will limit extra debug to that component only. Setting this option to '__', e.g. '_zmc_m1' will limit extra debug to that instance of the component only. This is ordinarily what you probably want to do. To debug scripts use their names without the .pl extension, e.g. '_zmvideo' and to debug issues with the web interface use '_web'. You can specify multiple targets by separating them with '|' characters.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_LEVEL", + default => 1, + description => "What level of extra debug should be enabled", + help => "There are 9 levels of debug available, with higher numbers being more debug and level 0 being no debug. However not all levels are used by all components. Also if there is debug at a high level it is usually likely to be output at such a volume that it may obstruct normal operation. For this reason you should set the level carefully and cautiously until the degree of debug you wish to see is present. Scripts and the web interface only have one level so this is an on/off type option for them.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => { db_type=>"integer", hint=>"1|2|3|4|5|6|7|8|9", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_FILE", + default => "/tmp/zm/zm_debug.log+", + description => "Where extra debug is output to", + help => "This option allows you to specify a different target for debug output. All components have a default log file which will norally be in /tmp or /var/log and this is where debug will be written to if this value is empty. Adding a path here will temporarily redirect debug, and other logging output, to this file. This option is a simple filename and you are debugging several components then they will all try and write to the same file with undesirable consequences. Appending a '+' to the filename will cause the file to be created with a '.' suffix containing your process id. In this way debug from each run of a component is kept separate. This is the recommended setting as it will also prevent subsequent runs from overwriting the same log. You should ensure that permissions are set up to allow writing to the file and directory specified here.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_CHECK_PERIOD", + default => "900", + description => "Time period used when calculating overall system health", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to indicate what period of historical events are used in this calculation. This value is expressed in seconds and is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_WAR_COUNT", + default => "1", + description => "Number of warnings indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alert state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_ERR_COUNT", + default => "1", + description => "Number of errors indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alert state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_FAT_COUNT", + default => "0", + description => "Number of fatal error indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alert state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_WAR_COUNT", + default => "100", + description => "Number of warnings indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alarm state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_ERR_COUNT", + default => "10", + description => "Number of errors indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alarm state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_FAT_COUNT", + default => "1", + description => "Number of fatal error indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alarm state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_RECORD_EVENT_STATS", + default => "yes", + description => "Record event statistical information, switch off if too slow", + help => "This version of ZoneMinder records detailed information about events in the Stats table. This can help in profiling what the optimum settings are for Zones though this is tricky at present. However in future releases this will be done more easily and intuitively, especially with a large sample of events. The default option of 'yes' allows this information to be collected now in readiness for this but if you are concerned about performance you can switch this off in which case no Stats information will be saved.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_RECORD_DIAG_IMAGES", + default => "no", + description => "Record intermediate alarm diagnostic images, can be very slow", + help => "In addition to recording event statistics you can also record the intermediate diagnostic images that display the results of the various checks and processing that occur when trying to determine if an alarm event has taken place. There are several of these images generated for each frame and zone for each alarm or alert frame so this can have a massive impact on performance. Only switch this setting on for debug or analysis purposes and remember to switch it off again once no longer required.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_DUMP_CORES", + default => "no", + description => "Create core files on unexpected process failure.", + help => "When an unrecoverable error occurs in a ZoneMinder binary process is has traditionally been trapped and the details written to logs to aid in remote analysis. However in some cases it is easier to diagnose the error if a core file, which is a memory dump of the process at the time of the error, is created. This can be interactively analysed in the debugger and may reveal more or better information than that available from the logs. This option is recommended for advanced users only otherwise leave at the default. Note using this option to trigger core files will mean that there will be no indication in the binary logs that a process has died, they will just stop, however the zmdc log will still contain an entry. Also note that you may have to explicitly enable core file creation on your system via the 'ulimit -c' command or other means otherwise no file will be created regardless of the value of this option.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_PATH_MAP", + default => "/dev/shm", + description => "Path to the mapped memory files that that ZoneMinder can use", + help => "ZoneMinder has historically used IPC shared memory for shared data between processes. This has it's advantages and limitations. This version of ZoneMinder can use an alternate method, mapped memory, instead with can be enabled with the --enable--mmap directive to configure. This requires less system configuration and is generally more flexible. However it requires each shared data segment to map onto a filesystem file. This option indicates where those mapped files go. You should ensure that this location has sufficient space for these files and for the best performance it should be a tmpfs file system or ramdisk otherwise disk access may render this method slower than the regular shared memory one.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SOCKS", + default => "/tmp/zm", + description => "Path to the various Unix domain socket files that ZoneMinder uses", + help => "ZoneMinder generally uses Unix domain sockets where possible. This reduces the need for port assignments and prevents external applications from possibly compromising the daemons. However each Unix socket requires a .sock file to be created. This option indicates where those socket files go.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_LOGS", + default => "/var/log/zm", + description => "Path to the various logs that the ZoneMinder daemons generate", + help => "There are various daemons that are used by ZoneMinder to perform various tasks. Most generate helpful log files and this is where they go. They can be deleted if not required for debugging.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SWAP", + default => "/tmp/zm", + description => "Path to location for temporary swap images used in streaming", + help => "Buffered playback requires temporary swap images to be stored for each instance of the streaming daemons. This option determines where these images will be stored. The images will actually be stored in sub directories beneath this location and will be automatically cleaned up after a period of time.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_WEB_TITLE_PREFIX", + default => "ZM", + description => "The title prefix displayed on each window", + help => "If you have more than one installation of ZoneMinder it can be helpful to display different titles for each one. Changing this option allows you to customise the window titles to include further information to aid identification.", + type => $types{string}, + category => "web", + }, + { + name => "ZM_WEB_RESIZE_CONSOLE", + default => "yes", + description => "Should the console window resize itself to fit", + help => "Traditionally the main ZoneMinder web console window has resized itself to shrink to a size small enough to list only the monitors that are actually present. This is intended to make the window more unobtrusize but may not be to everyones tastes, especially if opened in a tab in browsers which support this kind if layout. Switch this option off to have the console window size left to the users preference", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_POPUP_ON_ALARM", + default => "yes", + description => "Should the monitor window jump to the top if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to pop to the front if an alarm occurs when the window is minimised or behind another window. This is most useful if your monitors are over doors for example when they can pop up if someone comes to the doorway.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_X10", + default => "no", + description => "Support interfacing with X10 devices", + help => "If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.", + type => $types{boolean}, + category => "x10", + }, + { + name => "ZM_X10_DEVICE", + default => "/dev/ttyS0", + description => "What device is your X10 controller connected on", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.", + type => $types{abs_path}, + category => "x10", + }, + { + name => "ZM_X10_HOUSE_CODE", + default => "A", + description => "What X10 house code should be used", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.", + type => { db_type=>"string", hint=>"A-P", pattern=>qr|^([A-P])|i, format=>q( uc($1) ) }, + category => "x10", + }, + { + name => "ZM_X10_DB_RELOAD_INTERVAL", + default => "60", + description => "How often (in seconds) the X10 daemon reloads the monitors from the database", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "The zmx10 daemon periodically checks the database to find out what X10 events trigger, or result from, alarms. This option determines how frequently this check occurs, unless you change this area frequently this can be a fairly large value.", + type => $types{integer}, + category => "x10", + }, + { + name => "ZM_WEB_SOUND_ON_ALARM", + default => "no", + description => "Should the monitor window play a sound if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to play a sound to alert you if an alarm occurs.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_ALARM_SOUND", + default => "", + description => "The sound to play on alarm, put this in the sounds directory", + help => "You can specify a sound file to play if an alarm occurs whilst you are watching a live monitor stream. So long as your browser understands the format it does not need to be any particular type. This file should be placed in the sounds directory defined earlier.", + type => $types{file}, + requires => [ { name => "ZM_WEB_SOUND_ON_ALARM", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_COMPACT_MONTAGE", + default => "no", + description => "Compact the montage view by removing extra detail", + help => "The montage view shows the output of all of your active monitors in one window. This include a small menu and status information for each one. This can increase the web traffic and make the window larger than may be desired. Setting this option on removes all this extraneous information and just displays the images.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_FAST_DELETE", + default => "yes", + description => "Delete only event database records for speed", + help => "Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if your are trying to do a lot of events at once. It is recommended that you set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_STRICT_VIDEO_CONFIG", + default => "yes", + description => "Allow errors in setting video config to be fatal", + help => "With some video devices errors can be reported in setting the various video attributes when in fact the operation was successful. Switching this option off will still allow these errors to be reported but will not cause them to kill the video capture daemon. Note however that doing this will cause all errors to be ignored including those which are genuine and which may cause the video capture to not function correctly. Use this option with caution.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_SIGNAL_CHECK_POINTS", + default => "10", + description => "How many points in a captured image to check for signal loss", + help => "For locally attached video cameras ZoneMinder can check for signal loss by looking at a number of random points on each captured image. If all of these points are set to the same fixed colour then the camera is assumed to have lost signal. When this happens any open events are closed and a short one frame signal loss event is generated, as is another when the signal returns. This option defines how many points on each image to check. Note that this is a maximum, any points found to not have the check colour will abort any further checks so in most cases on a couple of points will actually be checked. Network and file based cameras are never checked.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_V4L_MULTI_BUFFER", + default => "yes", + description => "Use more than one buffer for Video 4 Linux devices", + help => "Performance when using Video 4 Linux devices is usually best if multiple buffers are used allowing the next image to be captured while the previous one is being processed. If you have multiple devices on a card sharing one input that requires switching then this approach can sometimes cause frames from one source to be mixed up with frames from another. Switching this option off prevents multi buffering resulting in slower but more stable image capture. This option is ignored for non-local cameras or if only one input is present on a capture chip. This option addresses a similar problem to the ZM_CAPTURES_PER_FRAME option and you should normally change the value of only one of the options at a time.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CAPTURES_PER_FRAME", + default => "1", + description => "How many images are captured per returned frame, for shared local cameras", + help => "If you are using cameras attached to a video capture card which forces multiple inputs to share one capture chip, it can sometimes produce images with interlaced frames reversed resulting in poor image quality and a distinctive comb edge appearance. Increasing this setting allows you to force additional image captures before one is selected as the captured frame. This allows the capture hardware to 'settle down' and produce better quality images at the price of lesser capture rates. This option has no effect on (a) network cameras, or (b) where multiple inputs do not share a capture chip. This option addresses a similar problem to the ZM_V4L_MULTI_BUFFER option and you should normally change the value of only one of the options at a time.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_FILTER_RELOAD_DELAY", + default => "300", + description => "How often (in seconds) filters are reloaded in zmfilter", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are reloaded from the database to get the latest versions or new filters. If you don't change filters very often this value can be set to a large value.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FILTER_EXECUTE_INTERVAL", + default => "60", + description => "How often (in seconds) to run automatic saved filters", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are executed on the saved event in the database. If you want a rapid response to new events this should be a smaller value, however this may increase the overall load on the system and affect performance of other elements.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_UPLOAD", + default => "no", + description => "Should ZoneMinder support uploading events from filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should be uploaded to a remote server for archiving. This option specifies whether this functionality should be available", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_FORMAT", + default => "tar", + description => "What format the uploaded events should be created in.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "Uploaded events may be stored in either .tar or .zip format, this option specifies which. Note that to use this you will need to have the Archive::Tar and/or Archive::Zip perl modules installed.", + type => { db_type=>"string", hint=>"tar|zip", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^t/ ? "tar" : "zip" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_COMPRESS", + default => "no", + description => "Should archive files be compressed", + help => "When the archive files are created they can be compressed. However in general since the images are compressed already this saves only a minimal amount of space versus utilising more CPU in their creation. Only enable if you have CPU to waste and are limited in disk space on your remote server or bandwidth.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_ANALYSE", + default => "no", + description => "Include the analysis files in the archive", + help => "When the archive files are created they can contain either just the captured frames or both the captured frames and, for frames that caused an alarm, the analysed image with the changed area highlighted. This option controls files are included. Only include analysed frames if you have a high bandwidth connection to the remote server or if you need help in figuring out what caused an alarm in the first place as archives with these files in can be considerably larger.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PROTOCOL", + default => "ftp", + description => "What protocol to use to upload events", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "ZoneMinder can upload events to a remote server using either FTP or SFTP. Regular FTP is widely supported but not necessarily very secure whereas SFTP (Secure FTP) runs over an ssh connection and so is encrypted and uses regular ssh ports. Note that to use this you will need to have the appropriate perl module, either Net::FTP or Net::SFTP installed depending on your choice.", + type => { db_type=>"string", hint=>"ftp|sftp", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^f/ ? "ftp" : "sftp" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_HOST", + default => "", + description => "The remote server to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_HOST", + default => "", + description => "The remote server to upload events to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PORT", + default => "", + description => "The port on the remote upload server, if not the default (SFTP only)", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are using the SFTP protocol then this option allows you to specify a particular port to use for connection. If this option is left blank then the default, port 22, is used. This option is ignored for FTP uploads.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_USER", + default => "", + description => "Your ftp username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the username that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_USER", + default => "", + description => "Remote server username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASS", + default => "", + description => "Your ftp password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the password that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_PASS", + default => "", + description => "Remote server password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_LOC_DIR", + default => "/tmp/zm", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_LOC_DIR", + default => "/tmp/zm", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the maximum ftp inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the maximum inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASSIVE", + default => "yes", + description => "Use passive ftp when uploading", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates that ftp transfers should be done in passive mode. This uses a single connection for all ftp activity and, whilst slower than active transfers, is more robust and likely to work from behind filewalls. This option is ignored for SFTP transfers.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "If your computer is behind a firewall or proxy you may need to set FTP to passive mode. In fact for simple transfers it makes little sense to do otherwise anyway but you can set this to 'No' if you wish.", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_DEBUG", + default => "no", + description => "Switch ftp debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be included in the zmfilter log file.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_DEBUG", + default => "no", + description => "Switch upload debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be generated by the underlying transfer modules and included in the logs.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_OPT_EMAIL", + default => "no", + description => "Should ZoneMinder email you details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details emailed to you at a designated email address. This will allow you to be notified of events as soon as they occur and also to quickly view the events directly. This option specifies whether this functionality should be available. The email created with this option can be any size and is intended to be sent to a regular email reader rather than a mobile device.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_EMAIL_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)" +body = " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder"', + description => "The text of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_EMAIL_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)", + description => "The subject of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the subject of the email that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_EMAIL_BODY", + default => " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder", + description => "The body of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_OPT_MESSAGE", + default => "no", + description => "Should ZoneMinder message you with details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details sent to you at a designated short message email address. This will allow you to be notified of events as soon as they occur. This option specifies whether this functionality should be available. The email created by this option will be brief and is intended to be sent to an SMS gateway or a minimal mail reader such as a mobile device or phone rather than a regular email reader.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_MESSAGE_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the short message email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_MESSAGE_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI%" +body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score."', + description => "The text of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_MESSAGE_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI%", + description => "The subject of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the subject of the message that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_MESSAGE_BODY", + default => "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.", + description => "The body of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_NEW_MAIL_MODULES", + default => "no", + description => "Use a newer perl method to send emails", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "Traditionally ZoneMinder has used the MIME::Entity perl module to construct and send notification emails and messages. Some people have reported problems with this module not being present at all or flexible enough for their needs. If you are one of those people this option allows you to select a new mailing method using MIME::Lite and Net::SMTP instead. This method was contributed by Ross Melin and should work for everyone but has not been extensively tested so currently is not selected by default.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_HOST", + default => "localhost", + description => "The host address of your SMTP mail server", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "If you have chosen SMTP as the method by which to send notification emails or messages then this option allows you to choose which SMTP server to use to send them. The default of localhost may work if you have the sendmail, exim or a similar daemon running however you may wish to enter your ISP's SMTP mail server here.", + type => $types{hostname}, + category => "mail", + }, + { + name => "ZM_FROM_EMAIL", + default => "", + description => "The email address you wish your event notifications to originate from", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can appear to come from a designated email address to help you with mail filtering etc. An address of something like ZoneMinder\@your.domain is recommended.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_URL", + default => "", + description => "The URL of your ZoneMinder installation", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. http://host.your.domain/zm.php.", + type => $types{url}, + category => "mail", + }, + { + name => "ZM_MAX_RESTART_DELAY", + default => "600", + description => "Maximum delay (in seconds) for daemon restart attempts.", + help => "The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_CHECK_INTERVAL", + default => "10", + description => "How often to check the capture daemons have not locked up", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_MAX_DELAY", + default => "5", + description => "The maximum delay allowed since the last captured image", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.", + type => $types{decimal}, + category => "system", + }, + { + + name => "ZM_RUN_AUDIT", + default => "yes", + description => "Run zmaudit to check data consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.", + type => $types{boolean}, + category => "system", + }, + { + + name => "ZM_AUDIT_CHECK_INTERVAL", + default => "900", + description => "How often to check database and filesystem consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FORCED_ALARM_SCORE", + default => "255", + description => "Score to give forced alarms", + help => "The 'zmu' utility can be used to force an alarm on a monitor rather than rely on the motion detection algorithms. This option determines what score to give these alarms to distinguish them from regular ones. It must be 255 or less.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_BULK_FRAME_INTERVAL", + default => "100", + description => "How often a bulk frame should be written to the database", + help => "Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation ('Record' or 'Mocord' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one 'bulk' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_EVENT_CLOSE_MODE", + default => "idle", + description => "When continuous events are closed.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.", + type => $types{boolean}, + type => { db_type=>"string", hint=>"time|idle|alarm", pattern=>qr|^([tia])|i, format=>q( ($1 =~ /^t/) ? "time" : ($1 =~ /^i/ ? "idle" : "time" ) ) }, + category => "config", + }, + # Deprecated, superseded by event close mode + { + name => "ZM_FORCE_CLOSE_EVENTS", + default => "no", + description => "Close events at section ends.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section and ordinarily this will prevent the event being closed until the motion has ceased. Switching this option on will force the event closed at the specified time regardless of any motion activity.", + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_CREATE_ANALYSIS_IMAGES", + default => "yes", + description => "Create analysed alarm images with motion outlined", + help => "By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_WEIGHTED_ALARM_CENTRES", + default => "no", + description => "Use a weighted algorithm to calculate the centre of an alarm", + help => "ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_EVENT_IMAGE_DIGITS", + default => "3", + description => "How many significant digits are used in event image numbering", + help => "As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_DEFAULT_ASPECT_RATIO", + default => "4:3", + description => "The default width:height aspect ratio used in monitors", + help => "When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format : and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.", + type => $types{string}, + category => "config", + }, + { + name => "ZM_USER_SELF_EDIT", + default => "no", + description => "Allow unprivileged users to change their details", + help => "Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_FRAME_SERVER", + default => "no", + description => "Should analysis farm out the writing of images to disk", + #requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ], + help => "In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_FRAME_SOCKET_SIZE", + default => "0", + description => "Specify the frame server socket buffer size if non-standard", + requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ], + help => "For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_CONTROL", + default => "no", + description => "Support controllable (e.g. PTZ) cameras", + help => "ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_OPT_TRIGGERS", + default => "no", + description => "Interface external event triggers via socket or device files", + help => "ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_CHECK_FOR_UPDATES", + default => "yes", + description => "Check with zoneminder.com for updated versions", + help => "From ZoneMinder version 1.17.0 onwards new versions are expected to be more frequent. To save checking manually for each new version ZoneMinder can check with the zoneminder.com website to determine the most recent release. These checks are infrequent, about once per week, and no personal or system information is transmitted other than your current version number. If you do not wish these checks to take place or your ZoneMinder system has no internet access you can switch these check off with this configuration variable", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_UPDATE_CHECK_PROXY", + default => "", + description => "Proxy url if required to access zoneminder.com", + help => "If you use a proxy to access the internet then ZoneMinder needs to know so it can access zoneminder.com to check for updates. If you do use a proxy enter the full proxy url here in the form of http://:/", + type => $types{string}, + category => "system", + }, + { + name => "ZM_SHM_KEY", + default => "0x7a6d0000", + description => "Shared memory root key to use", + help => "ZoneMinder uses shared memory to speed up communication between modules. To identify the right area to use shared memory keys are used. This option controls what the base key is, each monitor will have it's Id or'ed with this to get the actual key used. You will not normally need to change this value unless it clashes with another instance of ZoneMinder on the same machine. Only the first four hex digits are used, the lower four will be masked out and ignored.", + type => $types{hexadecimal}, + category => "system", + }, + # Deprecated, really no longer necessary + { + name => "ZM_WEB_REFRESH_METHOD", + default => "javascript", + description => "What method windows should use to refresh themselves", + help => "Many windows in Javascript need to refresh themselves to keep their information current. This option determines what method they should use to do this. Choosing 'javascript' means that each window will have a short JavaScript statement in with a timer to prompt the refresh. This is the most compatible method. Choosing 'http' means the refresh instruction is put in the HTTP header. This is a cleaner method but refreshes are interrupted or cancelled when a link in the window is clicked meaning that the window will no longer refresh and this would have to be done manually.", + type => { db_type=>"string", hint=>"javascript|http", pattern=>qr|^([jh])|i, format=>q( $1 =~ /^j/ ? "javascript" : "http" ) }, + category => "hidden", + }, + { + name => "ZM_WEB_EVENT_SORT_FIELD", + default => "DateTime", + description => "Default field the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what field is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"Id|Name|Cause|MonitorName|DateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore", pattern=>qr|.|, format=>q( $1 ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENT_SORT_ORDER", + default => "asc", + description => "Default order the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what order (ascending or descending) is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"asc|desc", pattern=>qr|^([ad])|i, format=>q( $1 =~ /^a/i ? "asc" : "desc" ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENTS_PER_PAGE", + default => "25", + description => "How many events to list per page in paged mode", + help => "In the event list view you can either list all events or just a page at a time. This option controls how many events are listed per page in paged mode and how often to repeat the column headers in non-paged mode.", + type => $types{integer}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMBS", + default => "no", + description => "Display mini-thumbnails of event images in event lists", + help => "Ordinarily the event lists just display text details of the events to save space and time. By switching this option on you can also display small thumbnails to help you identify events of interest. The size of these thumbnails is controlled by the following two options.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_WIDTH", + default => "48", + description => "The width of the thumbnails that appear in the event lists", + help => "This options controls the width of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a height instead in the next option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_HEIGHT", + default => "0", + description => "The height of the thumbnails that appear in the event lists", + help => "This options controls the height of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a width instead in the previous option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_USE_OBJECT_TAGS", + default => "yes", + description => "Wrap embed in object tags for media content", + help => "There are two methods of including media content in web pages. The most common way is use the EMBED tag which is able to give some indication of the type of content. However this is not a standard part of HTML. The official method is to use OBJECT tags which are able to give more information allowing the correct media viewers etc to be loaded. However these are less widely supported and content may be specifically tailored to a particular platform or player. This option controls whether media content is enclosed in EMBED tags only or whether, where appropriate, it is additionally wrapped in OBJECT tags. Currently OBJECT tags are only used in a limited number of circumstances but they may become more widespread in the future. It is suggested that you leave this option on unless you encounter problems playing some content.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_H_REFRESH_MAIN", + default => "300", + introduction => "There are now a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client.\n\nThe next few options control what happens when the client is running in 'high' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a local network or high speed link. In most cases the default values will be suitable as a starting point.", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_CYCLE", + default => "10", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_IMAGE", + default => "5", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_STATUS", + default => "3", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_EVENTS", + default => "30", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "highband", + }, + { + name => "ZM_WEB_H_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_BITRATE", + default => "150000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_MAXFPS", + default => "15", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_SCALE_THUMBS", + default => "no", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_AJAX_TIMEOUT", + default => "3000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_M_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + introduction => "The next few options control what happens when the client is running in 'medium' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a slower cable or DSL link. In most cases the default values will be suitable as a starting point.", + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_CYCLE", + default => "20", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_IMAGE", + default => "10", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_STATUS", + default => "5", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_EVENTS", + default => "60", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "medband", + }, + { + name => "ZM_WEB_M_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_BITRATE", + default => "75000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_MAXFPS", + default => "10", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_AJAX_TIMEOUT", + default => "5000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_L_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + introduction => "The next few options control what happens when the client is running in 'low' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a modem or slow link. In most cases the default values will be suitable as a starting point.", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_CYCLE", + default => "30", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_IMAGE", + default => "15", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_STATUS", + default => "10", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_EVENTS", + default => "180", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "lowband", + }, + { + name => "ZM_WEB_L_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_BITRATE", + default => "25000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_SHOW_PROGRESS", + default => "no", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_P_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_BITRATE", + default => "8000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_DYN_LAST_VERSION", + default => "", + description => "What the last version of ZoneMinder recorded from zoneminder.com is", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_CURR_VERSION", + default => "1.25.0", + description => "What the effective current version of ZoneMinder is, might be different from actual if versions ignored", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DB_VERSION", + default => "1.25.0", + description => "What the version of the database is, from zmupdate", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_LAST_CHECK", + default => "", + description => "When the last check for version from zoneminder.com was", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_NEXT_REMINDER", + default => "", + description => "When the earliest time to remind about versions will be", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DONATE_REMINDER_TIME", + default => 0, + description => "When the earliest time to remind about donations will be", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_SHOW_DONATE_REMINDER", + default => "yes", + description => "Remind about donations or not", + help => "", + type => $types{boolean}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_EYEZM_DEBUG", + default => "no", + description => "Switch additional debugging on for eyeZm Plugin", + help => "Enable or Disable extra debugging from the eyeZm Plugin. Extra debugging information will be displayed in it's own file (EYEZM_LOG_TO_FILE is set), or your Apache error log", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_TO_FILE", + default => "yes", + description => "When eyeZm Debugging is enabled, enabling this logs output to it's own file", + help => "When EYEZM_DEBUG is on and EYEZM_LOG_TO_FILE is on, output generated from the eyeZm Plugin will go to it's own file. Otherwise it will go to the apache error log.", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_FILE", + default => "/var/log/zm/zm_xml.log", + description => "Default filename to use when logging eyeZm Output and EYEZM_LOG_TO_FILE is enabled", + help => "This file will contain it's own output from the eyeZm Plugin when EYEZM_LOG_TO_FILE and EYEZM_DEBUG are both enabled", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_EVENT_VCODEC", + default => "mpeg4", + description => "Default video-codec to use for encoding events", + help => "The eyeZm Plugin calls FFMPEG externally to encode the captured images. If your FFMPEG is not built with support for H264, change this to MPEG-4. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+).", + type => { db_type=>"string", hint=>"mpeg4|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mpeg4" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_FEED_VCODEC", + default => "mjpeg", + description => "Default video-codec to use for streaming the live feed", + help => "Determines whether the live stream is generated using native MJPEG streaming with ZoneMinder, or H264 using FFMPEG and HTML-5 streaming. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+). This is just a default parameter, and can be overridden with eyeZm.", + type => { db_type=>"string", hint=>"mjpeg|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mjpeg" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_BR", + default => "96k", + description => "Default bit-rate to use with FFMPEG for H264 streaming", + help => "When using the eyeZm Plugin to stream H264 data, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_EVBR", + default => "128k", + description => "Default bit-rate to use with FFMPEG for H264 event viewing", + help => "When using the eyeZm Plugin to view events in H264, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_TIMEOUT", + default => "20", + description => "Timeout (sec) to wait for H264 stream to start before terminating", + help => "The eyeZm Plugin will attempt to spawn an H264 stream when requested, and require that it complete within the timeout specified. If you have a slow system or find through the logs that the H264 stream is not starting because the timeout is expiring, even though FFMPEG is running, try increasing this value. If you have a fast system, decreasing this value can improve the responsiveness when there are issues starting H264 streams", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_SEG_DURATION", + default => "3", + description => "Segment duration used for streaming using HTTP-5 Streaming protocol", + help => "The HTTP-5 Live Streaming Protocol segments the input video stream into small chunks of a duration specified by this parameter. Increasing the segment duration will help with choppy connections on the other end, but will increase the latency in starting a stream.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_PATH_PLUGINS", + default => "/usr/share/zm", + description => "Path to the plugin folder", + help => "3d-party plugins have to be placed here.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PLUGIN_EXTENSION", + default => ".zmpl", + description => "Default extension of plugins to found.", + help => "Default extension of plugins to found.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_PLUGINS_CONFIG_PATH", + default => "/usr/share/zm/plugins.conf", + description => "Path to the config file for plugins.", + help => "Path to the config file for plugins.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_LOAD_PLUGINS", + default => "no", + description => "Load and use 3d-party plugins", + help => "3d-party plugins will be loaded and used for analysing.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_TURNOFF_NATIVE_ANALYSIS", + default => "no", + description => "Turn native ZM\'s image analysis possibility off", + help => "Image analysis with ZM\'s motion detected function will be turned off. Only detection functions from loaded plugins will be used. Note, that if no plugins have be loaded, no detection will be done.", + type => $types{boolean}, + category => "config", + }, + +); + +our %options_hash = map { ( $_->{name}, $_ ) } @options; + +# This function should never need to be called explicitly, except if +# this module is 'require'd rather than 'use'd. See zmconfgen.pl. +sub initialiseConfig +{ + return if ( $configInitialised ); + + # Do some initial data munging to finish the data structures + # Create option ids + my $option_id = 0; + foreach my $option ( @options ) + { + if ( defined($option->{default}) ) + { + $option->{value} = $option->{default} + } + else + { + $option->{value} = ''; + } + #next if ( $option->{category} eq 'hidden' ); + $option->{id} = $option_id++; + } + $configInitialised = 1; +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigData - ZoneMinder Configuration Data module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigData; + use ZoneMinder::ConfigData qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigData module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control.pm new file mode 100644 index 000000000..2a646772d --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control.pm @@ -0,0 +1,205 @@ +# ========================================================================== +# +# ZoneMinder Base Control 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 base class definitions for the camera control +# protocol implementations +# +package ZoneMinder::Control; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Database qw(:all); + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my $id = shift; + my $self = {}; + $self->{name} = "PelcoD"; + if ( !defined($id) ) + { + Fatal( "No monitor defined when invoking protocol ".$self->{name} ); + } + $self->{id} = $id; + bless( $self, $class ); + return $self; +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + croak( "Can't access $name member of object of class $class" ); +} + +sub getKey() +{ + my $self = shift; + return( $self->{id} ); +} + +sub open +{ + my $self = shift; + Fatal( "No open method defined for protocol ".$self->{name} ); +} + +sub close +{ + my $self = shift; + Fatal( "No close method defined for protocol ".$self->{name} ); +} + +sub loadMonitor +{ + my $self = shift; + if ( !$self->{Monitor} ) + { + if ( !($self->{Monitor} = zmDbGetMonitor( $self->{id} )) ) + { + Fatal( "Monitor id ".$self->{id}." not found or not controllable" ); + } + if ( defined($self->{Monitor}->{AutoStopTimeout}) ) + { + # Convert to microseconds. + $self->{Monitor}->{AutoStopTimeout} = int(1000000*$self->{Monitor}->{AutoStopTimeout}); + } + } +} + +sub getParam +{ + my $self = shift; + my $params = shift; + my $name = shift; + my $default = shift; + + if ( defined($params->{$name}) ) + { + return( $params->{$name} ); + } + elsif ( defined($default) ) + { + return( $default ); + } + Fatal( "Missing mandatory parameter '$name'" ); +} + +sub executeCommand +{ + my $self = shift; + my $params = shift; + + $self->loadMonitor(); + + my $command = $params->{command}; + delete $params->{command}; + + #if ( !defined($self->{$command}) ) + #{ + #Fatal( "Unsupported command '$command'" ); + #} + &{$self->{$command}}( $self, $params ); +} + +sub printMsg() +{ + my $self = shift; + Fatal( "No printMsg method defined for protocol ".$self->{name} ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/AxisV2.pm new file mode 100644 index 000000000..e5a5882b9 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/AxisV2.pm @@ -0,0 +1,475 @@ +# ========================================================================== +# +# ZoneMinder Axis version 2 API Control Protocol 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 implementation of the Axis V2 API camera control +# protocol +# +package ZoneMinder::Control::AxisV2; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Axis V2 Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + #print( "http://$address/$cmd\n" ); + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "/axis-cgi/admin/restart.cgi"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=up"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=down"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=left"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=right"; + $self->sendCmd( $cmd ); +} + +sub moveConUpRight +{ + my $self = shift; + Debug( "Move Up/Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=upright"; + $self->sendCmd( $cmd ); +} + +sub moveConUpLeft +{ + my $self = shift; + Debug( "Move Up/Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=upleft"; + $self->sendCmd( $cmd ); +} + +sub moveConDownRight +{ + my $self = shift; + Debug( "Move Down/Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=downright"; + $self->sendCmd( $cmd ); +} + +sub moveConDownLeft +{ + my $self = shift; + Debug( "Move Down/Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=downleft"; + $self->sendCmd( $cmd ); +} + +sub moveMap +{ + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam( $params, 'xcoord' ); + my $ycoord = $self->getParam( $params, 'ycoord' ); + Debug( "Move Map to $xcoord,$ycoord" ); + my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}."&imageheight=".$self->{Monitor}->{Height}; + $self->sendCmd( $cmd ); +} + +sub moveRelUp +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelDown +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=-$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelLeft +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + Debug( "Step Left $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelRight +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + Debug( "Step Right $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelUpRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up/Right $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelUpLeft +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up/Left $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelDownRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down/Right $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelDownLeft +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down/Left $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub zoomRelTele +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Tele" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step"; + $self->sendCmd( $cmd ); +} + +sub zoomRelWide +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Wide" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step"; + $self->sendCmd( $cmd ); +} + +sub focusRelNear +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Near" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step"; + $self->sendCmd( $cmd ); +} + +sub focusRelFar +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Far" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step"; + $self->sendCmd( $cmd ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=on"; + $self->sendCmd( $cmd ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off"; + $self->sendCmd( $cmd ); +} + +sub irisRelOpen +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Iris Open" ); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step"; + $self->sendCmd( $cmd ); +} + +sub irisRelClose +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Iris Close" ); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step"; + $self->sendCmd( $cmd ); +} + +sub irisAuto +{ + my $self = shift; + Debug( "Iris Auto" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=on"; + $self->sendCmd( $cmd ); +} + +sub irisMan +{ + my $self = shift; + Debug( "Iris Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=off"; + $self->sendCmd( $cmd ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Clear Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Set Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Goto Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=home"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Ncs370.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Ncs370.pm new file mode 100644 index 000000000..358aecb2b --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Ncs370.pm @@ -0,0 +1,241 @@ +# ========================================================================== +# +# ZoneMinder Neu-Fusion Control Protocol 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 implementation of the Neu-Fusion NCS370 IP camera +# control protocol +# +package ZoneMinder::Control::Ncs370; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Ncs370 IP Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( POST=>"http://".$self->{Monitor}->{ControlAddress}."/PANTILTCONTROL.CGI" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=1"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=7"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=3"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=5"; + $self->sendCmd( $cmd ); +} + +sub moveConUpRight +{ + moveConUp(); + moveConRight(); +} + +sub moveConUpLeft +{ + moveConUp(); + moveConLeft(); +} + +sub moveConDownRight +{ + moveConDown(); + moveConRight(); +} + +sub moveConDownLeft +{ + moveConDown(); + moveConLeft(); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=4"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PanasonicIP.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PanasonicIP.pm new file mode 100644 index 000000000..643765e9f --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PanasonicIP.pm @@ -0,0 +1,322 @@ +# ========================================================================== +# +# ZoneMinder Panasonic IP Control Protocol 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 implementation of the Panasonic IP camera control +# protocol +# +package ZoneMinder::Control::PanasonicIP; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Panasonic IP Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "nphRestart?PAGE=Restart&Restart=OK"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "nphControlCamera?Direction=TiltUp"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "nphControlCamera?Direction=TiltDown"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "nphControlCamera?Direction=PanLeft"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "nphControlCamera?Direction=PanRight"; + $self->sendCmd( $cmd ); +} + +sub moveMap +{ + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam( $params, 'xcoord' ); + my $ycoord = $self->getParam( $params, 'ycoord' ); + Debug( "Move Map to $xcoord,$ycoord" ); + my $cmd = "nphControlCamera?Direction=Direct&NewPosition.x=$xcoord&NewPosition.y=$ycoord&Width=".$self->{Monitor}->{Width}."&Height=".$self->{Monitor}->{Height}; + $self->sendCmd( $cmd ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Tele" ); + my $cmd = "nphControlCamera?Direction=ZoomTele"; + $self->sendCmd( $cmd ); +} + +sub zoomConWide +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Wide" ); + my $cmd = "nphControlCamera?Direction=ZoomWide"; + $self->sendCmd( $cmd ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Near" ); + my $cmd = "nphControlCamera?Direction=FocusNear"; + $self->sendCmd( $cmd ); +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Far" ); + my $cmd = "nphControlCamera?Direction=FocusFar"; + $self->sendCmd( $cmd ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my $cmd = "nphControlCamera?Direction=FocusAuto"; + $self->sendCmd( $cmd ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off"; + $self->sendCmd( $cmd ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Clear Preset $preset" ); + my $cmd = "nphPresetNameCheck?Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Set Preset $preset" ); + my $cmd = "nphPresetNameCheck?PresetName=$preset&Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Goto Preset $preset" ); + my $cmd = "nphControlCamera?Direction=Preset&PresetOperation=Move&Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "nphControlCamera?Direction=HomePosition"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PelcoD.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PelcoD.pm new file mode 100644 index 000000000..6c507bd1a --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/PelcoD.pm @@ -0,0 +1,735 @@ +# ========================================================================== +# +# ZoneMinder Pelco-D Control Protocol 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 implementation of the Pelco-D camera control +# protocol +# +package ZoneMinder::Control::PelcoD; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Pelco-D Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use constant SYNC => 0xff; +use constant COMMAND_GAP => 100000; # In ms + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use Device::SerialPort; + $self->{port} = new Device::SerialPort( $self->{Monitor}->{ControlDevice} ); + $self->{port}->baudrate(2400); + $self->{port}->databits(8); + $self->{port}->parity('none'); + $self->{port}->stopbits(1); + $self->{port}->handshake('none'); + + $self->{port}->read_const_time(50); + $self->{port}->read_char_time(10); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; + $self->{port}->close(); +} + +sub printMsg +{ + if ( logDebugging() ) + { + my $self = shift; + my $msg = shift; + my $prefix = shift || ""; + $prefix = $prefix.": " if ( $prefix ); + + my $line_length = 16; + my $msg_len = int(@$msg); + + my $msg_str = $prefix; + for ( my $i = 0; $i < $msg_len; $i++ ) + { + if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) ) + { + $msg_str .= sprintf( "\n%*s", length($prefix), "" ); + } + $msg_str .= sprintf( "%02x ", $msg->[$i] ); + } + $msg_str .= "[".$msg_len."]"; + Debug( $msg_str ); + } +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $ack = shift || 0; + + my $result = undef; + + my $checksum = 0x00; + for ( my $i = 1; $i < int(@$cmd); $i++ ) + { + $checksum += $cmd->[$i]; + $checksum &= 0xff; + } + push( @$cmd, $checksum ); + + $self->printMsg( $cmd, "Tx" ); + my $id = $cmd->[0] & 0xf; + + my $tx_msg = pack( "C*", @$cmd ); + + #print( "Tx: ".length( $tx_msg )." bytes\n" ); + my $n_bytes = $self->{port}->write( $tx_msg ); + if ( !$n_bytes ) + { + Error( "Write failed: $!" ); + } + if ( $n_bytes != length($tx_msg) ) + { + Error( "Incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" ); + } + + if ( $ack ) + { + Debug( "Waiting for ack" ); + my $max_wait = 3; + my $now = time(); + while( 1 ) + { + my ( $count, $rx_msg ) = $self->{port}->read(4); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x40 ) + { + my $socket = $resp[1] & 0x0f; + Debug( "Got ack for socket $socket" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + Warning( "Response timeout" ); + last; + } + } + } +} + +sub remoteReset +{ + my $self = shift; + Debug( "Remote Reset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0f, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub resetDefaults +{ + my $self = shift; + Debug( "Reset Defaults" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x29, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub cameraOff +{ + my $self = shift; + Debug( "Camera Off" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x08, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub cameraOn +{ + my $self = shift; + Debug( "Camera On" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x88, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub autoScan +{ + my $self = shift; + Debug( "Auto Scan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x90, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub manScan +{ + my $self = shift; + Debug( "Manual Scan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x10, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub stop +{ + my $self = shift; + Debug( "Stop" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub moveConUp +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x08, 0x00, $speed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConDown +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x10, 0x00, $speed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConLeft +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x04, $speed, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConRight +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x02, $speed, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0c, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0a, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x14, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x12, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveStop +{ + my $self = shift; + Debug( "Move Stop" ); + $self->stop(); +} + +sub flip180 +{ + my $self = shift; + Debug( "Flip 180" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x21 ); + $self->sendCmd( \@msg ); +} + +sub zeroPan +{ + my $self = shift; + Debug( "Zero Pan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22 ); + $self->sendCmd( \@msg ); +} + +sub _setZoomSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Zoom Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x25, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub zoomStop +{ + my $self = shift; + Debug( "Zoom Stop" ); + $self->stop(); + $self->_setZoomSpeed( 0 ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Tele" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x20, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomConWide +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Wide" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x40, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub _setFocusSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Focus Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Near" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x01, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Far" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x80, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusStop +{ + my $self = shift; + Debug( "Focus Stop" ); + $self->stop(); + $self->_setFocusSpeed( 0 ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Man" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x02 ); + $self->sendCmd( \@msg ); +} + +sub _setIrisSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Iris Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub irisConClose +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Close" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x04, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisConOpen +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Open" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x02, 0x80, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisStop +{ + my $self = shift; + Debug( "Iris Stop" ); + $self->stop(); + $self->_setIrisSpeed( 0 ); +} + +sub irisAuto +{ + my $self = shift; + Debug( "Iris Auto" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub irisMan +{ + my $self = shift; + Debug( "Iris Man" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x02 ); + $self->sendCmd( \@msg ); +} + +sub writeScreen +{ + my $self = shift; + my $params = shift; + my $string = $self->getParam( $params, 'string' ); + Debug( "Writing '$string' to screen" ); + + my @chars = unpack( "C*", $string ); + for ( my $i = 0; $i < length($string); $i++ ) + { + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x15, $i, $chars[$i] ); + $self->sendCmd( \@msg ); + usleep( COMMAND_GAP ); + } +} + +sub clearScreen +{ + my $self = shift; + Debug( "Clear Screen" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x17, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub clearPreset +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Clear Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x05, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Set Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x03, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Goto Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22 ); + $self->sendCmd( \@msg ); +} + +sub reset +{ + my $self = shift; + Debug( "Reset" ); + $self->remoteReset(); + $self->resetDefaults(); +} + +sub wake +{ + my $self = shift; + Debug( "Wake" ); + $self->cameraOn(); +} + +sub sleep +{ + my $self = shift; + Debug( "Sleep" ); + $self->cameraOff(); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Visca.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Visca.pm new file mode 100644 index 000000000..37f30dc09 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/Visca.pm @@ -0,0 +1,668 @@ +# ========================================================================== +# +# ZoneMinder Visca Control Protocol 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 implementation of the Visca camera control +# protocol +# +package ZoneMinder::Control::Visca; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Visca Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use constant SYNC => 0xff; +use constant COMMAND_GAP => 100000; # In ms + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use Device::SerialPort; + $self->{port} = new Device::SerialPort( $self->{Monitor}->{ControlDevice} ); + $self->{port}->baudrate(9600); + $self->{port}->databits(8); + $self->{port}->parity('none'); + $self->{port}->stopbits(1); + $self->{port}->handshake('rts'); + $self->{port}->stty_echo(0); + + #$self->{port}->read_const_time(250); + $self->{port}->read_char_time(2); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; + $self->{port}->close(); +} + +sub printMsg +{ + if ( logDebugging() ) + { + my $self = shift; + my $msg = shift; + my $prefix = shift || ""; + $prefix = $prefix.": " if ( $prefix ); + + my $line_length = 16; + my $msg_len = int(@$msg); + + my $msg_str = $prefix; + for ( my $i = 0; $i < $msg_len; $i++ ) + { + if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) ) + { + $msg_str .= sprintf( "\n%*s", length($prefix), "" ); + } + $msg_str .= sprintf( "%02x ", $msg->[$i] ); + } + $msg_str .= "[".$msg_len."]"; + Debug( $msg_str ); + } +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $ack = shift || 0; + my $cmp = shift || 0; + + my $result = undef; + + $self->printMsg( $cmd, "Tx" ); + my $id = $cmd->[0] & 0xf; + + my $tx_msg = pack( "C*", @$cmd ); + + #print( "Tx: ".length( $tx_msg )." bytes\n" ); + my $n_bytes = $self->{port}->write( $tx_msg ); + if ( !$n_bytes ) + { + Error( "Write failed: $!" ); + } + if ( $n_bytes != length($tx_msg) ) + { + Error( "Incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" ); + } + + if ( $ack ) + { + Debug( "Waiting for ack" ); + my $max_wait = 3; + my $now = time(); + while( 1 ) + { + my ( $count, $rx_msg ) = $self->{port}->read(4); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + $self->printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x40 ) + { + my $socket = $resp[1] & 0x0f; + Debug( "Got ack for socket $socket" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + last; + } + } + } + + if ( $cmp ) + { + Debug( "Waiting for command complete" ); + my $max_wait = 10; + my $now = time(); + while( 1 ) + { + #print( "Waiting\n" ); + my ( $count, $rx_msg ) = $self->{port}->read(16); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + $self->printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x50 ) + { + Debug( "Got command complete" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + last; + } + } + } + return( $result ); +} + +sub cameraOff +{ + my $self = shift; + Debug( "Camera Off\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x00, 0x0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub cameraOn +{ + my $self = shift; + Debug( "Camera On\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x00, 0x2, SYNC ); + $self->sendCmd( \@msg ); +} + +sub stop +{ + my $self = shift; + Debug( "Stop\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveConUp +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConDown +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub movConLeft +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $speed, 0x00, 0x01, 0x03, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConRight +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $speed, 0x00, 0x02, 0x03, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveUpLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveUpRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveDownLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveDownRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveRelUp +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, SYNC ); + + $self->sendCmd( \@msg ); +} + +sub moveRelDown +{ + my $self = shift; + my $params = shift; + my $step = -$self->getParam( $params, 'tiltstep' ); + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelLeft +{ + my $self = shift; + my $params = shift; + my $step = -$self->getParam( $params, 'panstep' ); + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + Debug( "Step Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelRight +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + Debug( "Step Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelUpLeft +{ + my $self = shift; + my $params = shift; + my $panstep = -$self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelUpRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelDownLeft +{ + my $self = shift; + my $params = shift; + my $panstep = -$self->getParam( $params, 'panstep' ); + my $tiltstep = -$self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelDownRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = -$self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x06 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Tele" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x20|$speed, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomWide +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x06 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Wide" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x30|$speed, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomStop +{ + my $self = shift; + my $params = shift; + Debug( "Zoom Stop" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + Debug( "Focus Near" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + Debug( "Focus Far" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x02, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusStop +{ + my $self = shift; + my $params = shift; + Debug( "Focus Stop" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusAuto +{ + my $self = shift; + my $params = shift; + Debug( "Focus Auto" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x38, 0x02, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusMan +{ + my $self = shift; + my $params = shift; + Debug( "Focus Man" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x38, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Clear Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x00, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Set Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x01, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Goto Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x02, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetHome +{ + my $self = shift; + my $params = shift; + Debug( "Home Preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x04, SYNC ); + $self->sendCmd( \@msg ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/mjpgStreamer.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/mjpgStreamer.pm new file mode 100644 index 000000000..33a15cba1 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Control/mjpgStreamer.pm @@ -0,0 +1,252 @@ +# ========================================================================== +# +# ZoneMinder mjpg STreamer Control Protocol Module, $Date: 2007-11-04 17:30:29 +0000 (Sun, 04 Nov 2007) $, $Revision: 2229 $ +# Copyright (C) 2003, 2004, 2005, 2006 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 implementation of the mjpg streamer camera control +# protocol +# +package ZoneMinder::Control::mjpgStreamer; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# mjpgSTreamer Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + Debug( "Camera New" ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + Debug( "Camera AUTOLOAD" ); + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + Debug( "Camera open" ); + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub Up +{ + my $self = shift; + $self->moveConUp(); +} + +sub Down +{ + my $self = shift; + $self->moveConDown(); +} + +sub Left +{ + my $self = shift; + $self->moveConLeft(); +} + +sub Right +{ + my $self = shift; + $self->moveConRight(); +} + + +sub reset +{ + my $self = shift; + $self->cameraReset(); +} + + + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "?action=command&command=reset_pan_tilt"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "?action=command&command=tilt_minus"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "?action=command&command=tilt_plus"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "?action=command&command=pan_plus"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "?action=command&command=pan_minus"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005 by 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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Database.pm new file mode 100644 index 000000000..d0bae5dde --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Database.pm @@ -0,0 +1,238 @@ +# ========================================================================== +# +# ZoneMinder Database 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::Database; + +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( + zmDbConnect + zmDbDisconnect + zmDbGetMonitors + zmDbGetMonitor + zmDbGetMonitorAndControl + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Database Access +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Carp; + +our $dbh = undef; + +sub zmDbConnect( ;$ ) +{ + my $force = shift; + if ( $force ) + { + zmDbDisconnect(); + } + if ( !defined( $dbh ) ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + + if ( defined($port) ) + { + $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".$host.";port=".$port, ZM_DB_USER, ZM_DB_PASS ); + } + else + { + $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + } + $dbh->trace( 0 ); + } + return( $dbh ); +} + +sub zmDbDisconnect() +{ + if ( defined( $dbh ) ) + { + $dbh->disconnect(); + $dbh = undef; + } +} + +use constant DB_MON_ALL => 0; # All monitors +use constant DB_MON_CAPT => 1; # All monitors that are capturing +use constant DB_MON_ACTIVE => 2; # All monitors that are active +use constant DB_MON_MOTION => 3; # All monitors that are doing motion detection +use constant DB_MON_RECORD => 4; # All monitors that are doing unconditional recording +use constant DB_MON_PASSIVE => 5; # All monitors that are in nodect state + +sub zmDbGetMonitors( ;$ ) +{ + zmDbConnect(); + + my $function = shift || DB_MON_ALL; + my $sql = "select * from Monitors"; + + if ( $function ) + { + if ( $function == DB_MON_CAPT ) + { + $sql .= " where Function >= 'Monitor'"; + } + elsif ( $function == DB_MON_ACTIVE ) + { + $sql .= " where Function > 'Monitor'"; + } + elsif ( $function == DB_MON_MOTION ) + { + $sql .= " where Function = 'Modect' or Function = 'Mocord'"; + } + elsif ( $function == DB_MON_RECORD ) + { + $sql .= " where Function = 'Record' or Function = 'Mocord'"; + } + elsif ( $function == DB_MON_PASSIVE ) + { + $sql .= " where Function = 'Nodect'"; + } + } + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute '$sql': ".$sth->errstr() ); + + my @monitors; + while( my $monitor = $sth->fetchrow_hashref() ) + { + push( @monitors, $monitor ); + } + $sth->finish(); + return( \@monitors ); +} + +sub zmDbGetMonitor( $ ) +{ + zmDbConnect(); + + my $id = shift; + + return( undef ) if ( !defined($id) ); + + my $sql = "select * from Monitors where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $id ) or croak( "Can't execute '$sql': ".$sth->errstr() ); + my $monitor = $sth->fetchrow_hashref(); + + return( $monitor ); +} + +sub zmDbGetMonitorAndControl( $ ) +{ + zmDbConnect(); + + my $id = shift; + + return( undef ) if ( !defined($id) ); + + my $sql = "select C.*,M.*,C.Protocol from Monitors as M inner join Controls as C on (M.ControlId = C.Id) where M.Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $id ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + my $monitor = $sth->fetchrow_hashref(); + + return( $monitor ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/General.pm new file mode 100644 index 000000000..5af7150a8 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/General.pm @@ -0,0 +1,768 @@ +# ========================================================================== +# +# ZoneMinder General Utility 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::General; + +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( + executeShellCommand + getCmdFormat + runCommand + setFileOwner + getEventPath + createEventPath + createEvent + deleteEventFiles + makePath + jsonEncode + jsonDecode + ) ] +); +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; + +# For running general shell commands +sub executeShellCommand( $ ) +{ + my $command = shift; + my $output = qx( $command ); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + Debug( "Command: $command\n" ); + chomp( $output ); + Debug( "Output: $output\n" ); + } + return( $status ); +} + +sub getCmdFormat() +{ + Debug( "Testing valid shell syntax\n" ); + + my ( $name ) = getpwuid( $> ); + if ( $name eq ZM_WEB_USER ) + { + Debug( "Running as '$name', su commands not needed\n" ); + return( "" ); + } + + my $null_command = "true"; + + my $prefix = "sudo -u ".ZM_WEB_USER." "; + my $suffix = ""; + my $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + $command .= " > /dev/null 2>&1"; + my $output = qx($command); + my $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + + $prefix = "su ".ZM_WEB_USER." --shell=/bin/sh --command='"; + $suffix = "'"; + $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + my $output = qx($command); + my $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + + $prefix = "su ".ZM_WEB_USER." -c '"; + $suffix = "'"; + $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + $output = qx($command); + $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + } + } + } + Error( "Unable to find valid 'su' syntax\n" ); + exit( -1 ); +} + +our $testedShellSyntax = 0; +our ( $cmdPrefix, $cmdSuffix ); + +# For running ZM daemons etc +sub runCommand( $ ) +{ + if ( !$testedShellSyntax ) + { + # Determine the appropriate syntax for the su command + ( $cmdPrefix, $cmdSuffix ) = getCmdFormat(); + $testedShellSyntax = !undef; + } + + my $command = shift; + $command = ZM_PATH_BIN."/".$command; + if ( $cmdPrefix ) + { + $command = $cmdPrefix.$command.$cmdSuffix; + } + Debug( "Command: $command\n" ); + my $output = qx($command); + my $status = $? >> 8; + chomp( $output ); + if ( $status || logDebugging() ) + { + if ( $status ) + { + Error( "Unable to run \"$command\", output is \"$output\"\n" ); + exit( -1 ); + } + else + { + Debug( "Output: $output\n" ); + } + } + return( $output ); +} + +sub getEventPath( $ ) +{ + my $event = shift; + + my $event_path = ""; + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.strftime( "%y/%m/%d/%H/%M/%S", localtime($event->{Time}) ); + } + else + { + $event_path = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id}; + } + $event_path = ZM_PATH_WEB.'/'.$event_path if ( index(ZM_DIR_EVENTS,'/') != 0 ); + return( $event_path ); +} + +sub createEventPath( $ ) +{ + # + # WARNING assumes running from events directory + # + my $event = shift; + my $eventRootPath = (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + my $eventPath = $eventRootPath.'/'.$event->{MonitorId}; + + if ( ZM_USE_DEEP_STORAGE ) + { + my @startTime = localtime( $event->{StartTime} ); + + my @datetimeParts = (); + $datetimeParts[0] = sprintf( "%02d", $startTime[5]-100 ); + $datetimeParts[1] = sprintf( "%02d", $startTime[4]+1 ); + $datetimeParts[2] = sprintf( "%02d", $startTime[3] ); + $datetimeParts[3] = sprintf( "%02d", $startTime[2] ); + $datetimeParts[4] = sprintf( "%02d", $startTime[1] ); + $datetimeParts[5] = sprintf( "%02d", $startTime[0] ); + + my $datePath = join('/',@datetimeParts[0..2]); + my $timePath = join('/',@datetimeParts[3..5]); + + makePath( $datePath, $eventPath ); + $eventPath .= '/'.$datePath; + + # Create event id symlink + my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + symlink( $timePath, $idFile ) or Fatal( "Can't symlink $idFile -> $eventPath: $!" ); + + makePath( $timePath, $eventPath ); + $eventPath .= '/'.$timePath; + setFileOwner( $idFile ); # Must come after directory has been created + + # Create empty id tag file + $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + open( ID_FP, ">$idFile" ) or Fatal( "Can't open $idFile: $!" ); + close( ID_FP ); + setFileOwner( $idFile ); + } + else + { + makePath( $event->{Id}, $eventPath ); + $eventPath .= '/'.$event->{Id}; + + my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + open( ID_FP, ">$idFile" ) or Fatal( "Can't open $idFile: $!" ); + close( ID_FP ); + setFileOwner( $idFile ); + } + return( $eventPath ); +} + +use Data::Dumper; + +our $_setFileOwner = undef; +our ( $_ownerUid, $_ownerGid ); + +sub _checkProcessOwner() +{ + if ( !defined($_setFileOwner) ) + { + my ( $processOwner ) = getpwuid( $> ); + if ( $processOwner ne ZM_WEB_USER ) + { + # Not running as web user, so should be root in whch case chown the temporary directory + ( my $ownerName, my $ownerPass, $_ownerUid, $_ownerGid ) = getpwnam( ZM_WEB_USER ) or Fatal( "Can't get user details for web user '".ZM_WEB_USER."': $!" ); + $_setFileOwner = 1; + } + else + { + $_setFileOwner = 0; + } + } + return( $_setFileOwner ); +} + +sub setFileOwner( $ ) +{ + my $file = shift; + + if ( _checkProcessOwner() ) + { + chown( $_ownerUid, $_ownerGid, $file ) or Fatal( "Can't change ownership of file '$file' to '".ZM_WEB_USER.":".ZM_WEB_GROUP."': $!" ); + } +} + +our $_hasImageInfo = undef; + +sub _checkForImageInfo() +{ + if ( !defined($_hasImageInfo) ) + { + my $result = eval + { + require Image::Info; + Image::Info->import(); + }; + $_hasImageInfo = $@?0:1; + } + return( $_hasImageInfo ); +} + +sub createEvent( $;$ ) +{ + my $event = shift; + + Debug( "Creating event" ); + #print( Dumper( $event )."\n" ); + + _checkForImageInfo(); + + my $dbh = zmDbConnect(); + + if ( $event->{monitor} ) + { + $event->{MonitorId} = $event->{monitor}->{Id}; + } + elsif ( $event->{MonitorId} ) + { + my $sql = "select * from Monitors where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{MonitorId} ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + $event->{monitor} = $sth->fetchrow_hashref() or Fatal( "Unable to create event, can't load monitor with id '".$event->{MonitorId}."'" ); + $sth->finish(); + } + else + { + Fatal( "Unable to create event, no monitor or monitor id supplied" ); + } + $event->{Name} = "New Event" unless( $event->{Name} ); + $event->{Frames} = int(@{$event->{frames}}); + $event->{TotScore} = $event->{MaxScore} = 0; + + my $lastTimestamp = 0.0; + foreach my $frame ( @{$event->{frames}} ) + { + if ( !$event->{Width} ) + { + if ( $_hasImageInfo ) + { + my $imageInfo = Image::Info::image_info( $frame->{imagePath} ); + if ( $imageInfo->{error} ) + { + Error( "Unable to extract image info from '".$frame->{imagePath}."': ".$imageInfo->{error} ); + } + else + { + ( $event->{Width}, $event->{Height} ) = Image::Info::dim( $imageInfo ); + } + } + } + $frame->{Type} = $frame->{Score}>0?'Alarm':'Normal' unless( $frame->{Type} ); + $frame->{Delta} = $lastTimestamp?($frame->{TimeStamp}-$lastTimestamp):0.0; + $event->{StartTime} = $frame->{TimeStamp} unless ( $event->{StartTime} ); + $event->{TotScore} += $frame->{Score}; + $event->{MaxScore} = $frame->{Score} if ( $frame->{Score} > $event->{MaxScore} ); + $event->{AlarmFrames}++ if ( $frame->{Type} eq 'Alarm' ); + $event->{EndTime} = $frame->{TimeStamp}; + $lastTimestamp = $frame->{TimeStamp}; + } + $event->{Width} = $event->{monitor}->{Width} unless( $event->{Width} ); + $event->{Height} = $event->{monitor}->{Height} unless( $event->{Height} ); + $event->{AvgScore} = $event->{TotScore}/int($event->{AlarmFrames}); + $event->{Length} = $event->{EndTime} - $event->{StartTime}; + + my %formats = ( + StartTime => 'from_unixtime(?)', + EndTime => 'from_unixtime(?)', + ); + + my ( @fields, @formats, @values ); + while ( my ( $field, $value ) = each( %$event ) ) + { + next unless $field =~ /^[A-Z]/; + push( @fields, $field ); + push( @formats, ($formats{$field} or '?') ); + push( @values, $event->{$field} ); + } + + my $sql = "insert into Events (".join(',',@fields).") values (".join(',',@formats).")"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + $event->{Id} = $dbh->{mysql_insertid}; + Info( "Created event ".$event->{Id} ); + + if ( $event->{EndTime} ) + { + $event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id} if ( $event->{Name} eq 'New Event' ); + my $sql = "update Events set Name = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Name}, $event->{Id} ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + } + + my $eventPath = createEventPath( $event ); + + my %frameFormats = ( + TimeStamp => 'from_unixtime(?)', + ); + my $frameId = 1; + foreach my $frame ( @{$event->{frames}} ) + { + $frame->{EventId} = $event->{Id}; + $frame->{FrameId} = $frameId++; + + my ( @fields, @formats, @values ); + while ( my ( $field, $value ) = each( %$frame ) ) + { + next unless $field =~ /^[A-Z]/; + push( @fields, $field ); + push( @formats, ($frameFormats{$field} or '?') ); + push( @values, $frame->{$field} ); + } + + my $sql = "insert into Frames (".join(',',@fields).") values (".join(',',@formats).")"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + #$frame->{FrameId} = $dbh->{mysql_insertid}; + if ( $frame->{imagePath} ) + { + $frame->{capturePath} = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $eventPath, $frame->{FrameId} ); + rename( $frame->{imagePath}, $frame->{capturePath} ) or Fatal( "Can't copy ".$frame->{imagePath}." to ".$frame->{capturePath}.": $!" ); + setFileOwner( $frame->{capturePath} ); + if ( 0 && ZM_CREATE_ANALYSIS_IMAGES ) + { + $frame->{analysePath} = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $eventPath, $frame->{FrameId} ); + link( $frame->{capturePath}, $frame->{analysePath} ) or Fatal( "Can't link ".$frame->{capturePath}." to ".$frame->{analysePath}.": $!" ); + setFileOwner( $frame->{analysePath} ); + } + } + } +} + +sub addEventImage( $$ ) +{ + my $event = shift; + my $frame = shift; + + # TBD +} + +sub updateEvent( $ ) +{ + my $event = shift; + + if ( !$event->{EventId} ) + { + Error( "Unable to update event, no event id supplied" ); + return( 0 ); + } + + my $dbh = zmDbConnect(); + + $event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id} if ( $event->{Name} eq 'New Event' ); + + my %formats = ( + StartTime => 'from_unixtime(?)', + EndTime => 'from_unixtime(?)', + ); + + my ( @values, @sets ); + while ( my ( $field, $value ) = each( %$event ) ) + { + next if ( $field eq 'Id' ); + push( @values, $event->{$field} ); + push( @sets, $field." = ".($formats{$field} or '?') ); + } + my $sql = "update Events set ".join(',',@sets)." where Id = ?"; + push( @values, $event->{Id} ); + + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); +} + +sub deleteEventFiles( $;$ ) +{ + # + # WARNING assumes running from events directory + # + my $event_id = shift; + my $monitor_id = shift; + $monitor_id = '*' if ( !defined($monitor_id) ); + + if ( ZM_USE_DEEP_STORAGE ) + { + my $link_path = $monitor_id."/*/*/*/.".$event_id; + #Debug( "LP1:$link_path" ); + my @links = glob($link_path); + #Debug( "L:".$links[0].": $!" ); + if ( @links ) + { + ( $link_path ) = ( $links[0] =~ /^(.*)$/ ); # De-taint + #Debug( "LP2:$link_path" ); + + ( my $day_path = $link_path ) =~ s/\.\d+//; + #Debug( "DP:$day_path" ); + my $event_path = $day_path.readlink( $link_path ); + ( $event_path ) = ( $event_path =~ /^(.*)$/ ); # De-taint + #Debug( "EP:$event_path" ); + my $command = "/bin/rm -rf ".$event_path; + #Debug( "C:$command" ); + executeShellCommand( $command ); + + unlink( $link_path ) or Error( "Unable to unlink '$link_path': $!" ); + my @path_parts = split( /\//, $event_path ); + for ( my $i = int(@path_parts)-2; $i >= 1; $i-- ) + { + my $delete_path = join( '/', @path_parts[0..$i] ); + #Debug( "DP$i:$delete_path" ); + my @has_files = glob( $delete_path."/*" ); + #Debug( "HF1:".$has_files[0] ) if ( @has_files ); + last if ( @has_files ); + @has_files = glob( $delete_path."/.[0-9]*" ); + #Debug( "HF2:".$has_files[0] ) if ( @has_files ); + last if ( @has_files ); + my $command = "/bin/rm -rf ".$delete_path; + executeShellCommand( $command ); + } + } + } + else + { + my $command = "/bin/rm -rf $monitor_id/$event_id"; + executeShellCommand( $command ); + } +} + +sub makePath( $;$ ) +{ + my $path = shift; + my $root = shift; + $root = (( $path =~ m|^/| )?'':'.' ) unless( $root ); + + Debug( "Creating path '$path' in $root'\n" ); + my @parts = split( '/', $path ); + my $fullPath = $root; + foreach my $dir ( @parts ) + { + $fullPath .= '/'.$dir; + if ( !-d $fullPath ) + { + if ( -e $fullPath ) + { + Fatal( "Can't create '$fullPath', already exists as non directory" ); + } + else + { + Debug( "Creating '$fullPath'\n" ); + mkdir( $fullPath, 0755 ) or Fatal( "Can't mkdir '$fullPath': $!" ); + setFileOwner( $fullPath ); + } + } + } + return( $fullPath ); +} + +our $testedJSON = 0; +our $hasJSONAny = 0; + +sub _testJSON +{ + return if ( $testedJSON ); + my $result = eval + { + require JSON::Any; + JSON::Any->import(); + }; + $testedJSON = 1; + $hasJSONAny = 1 if ( $result ); +} + +sub _getJSONType( $ ) +{ + my $value = shift; + return( 'null' ) unless( defined($value) ); + return( 'integer' ) if ( $value =~ /^\d+$/ ); + return( 'double' ) if ( $value =~ /^\d+$/ ); + return( 'hash' ) if ( ref($value) eq 'HASH' ); + return( 'array' ) if ( ref($value) eq 'ARRAY' ); + return( 'string' ); +} + +sub jsonEncode( $ ); + +sub jsonEncode( $ ) +{ + my $value = shift; + + _testJSON(); + if ( $hasJSONAny ) + { + my $string = eval { JSON::Any->objToJson( $value ) }; + Fatal( "Unable to encode object to JSON: $@" ) unless( $string ); + return( $string ); + } + + my $type = _getJSONType($value); + if ( $type eq 'integer' || $type eq 'double' ) + { + return( $value ); + } + elsif ( $type eq 'boolean' ) + { + return( $value?'true':'false' ); + } + elsif ( $type eq 'string' ) + { + $value =~ s|(["\\/])|\\$1|g; + $value =~ s|\r?\n|\n|g; + return( '"'.$value.'"' ); + } + elsif ( $type eq 'null' ) + { + return( 'null' ); + } + elsif ( $type eq 'array' ) + { + return( '['.join( ',', map { jsonEncode( $_ ) } @$value ).']' ); + } + elsif ( $type eq 'hash' ) + { + my $result = '{'; + while ( my ( $subKey=>$subValue ) = each( %$value ) ) + { + $result .= ',' if ( $result ne '{' ); + $result .= '"'.$subKey.'":'.jsonEncode( $subValue ); + } + return( $result.'}' ); + } + else + { + Fatal( "Unexpected type '$type'" ); + } +} + +sub jsonDecode( $ ) +{ + my $value = shift; + + _testJSON(); + if ( $hasJSONAny ) + { + my $object = eval { JSON::Any->jsonToObj( $value ) }; + Fatal( "Unable to decode JSON string '$value': $@" ) unless( $object ); + return( $object ); + } + + my $comment = 0; + my $unescape = 0; + my $out = ''; + my @chars = split( //, $value ); + for ( my $i = 0; $i < @chars; $i++ ) + { + if ( !$comment ) + { + if ( $chars[$i] eq ':' ) + { + $out .= '=>'; + } + else + { + $out .= $chars[$i]; + } + } + elsif ( !$unescape ) + { + if ( $chars[$i] eq '\\' ) + { + $unescape = 1; + } + else + { + $out .= $chars[$i]; + } + } + else + { + if ( $chars[$i] ne '/' ) + { + $out .= '\\'; + } + $out .= $chars[$i]; + $unescape = 0; + } + if ( $chars[$i] eq '"' ) + { + $comment = !$comment; + } + } + $out =~ s/=>true/=>1/g; + $out =~ s/=>false/=>0/g; + $out =~ s/=>null/=>undef/g; + $out =~ s/`/'/g; + $out =~ s/qx/qq/g; + ( $out ) = $out =~ m/^({.+})$/; # Detaint and check it's a valid object syntax + my $result = eval $out; + Fatal( $@ ) if ( $@ ); + return( $result ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Logger.pm new file mode 100644 index 000000000..46095be2e --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Logger.pm @@ -0,0 +1,861 @@ +# ========================================================================== +# +# ZoneMinder Logger 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::Logger; + +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 = ( + 'constants' => [ qw( + DEBUG + INFO + WARNING + ERROR + FATAL + PANIC + NOLOG + ) ], + 'functions' => [ qw( + logInit + logReinit + logTerm + logSetSignal + logClearSignal + logDebugging + logLevel + logTermLevel + logDatabaseLevel + logFileLevel + logSyslogLevel + Mark + Dump + Debug + Info + Warning + Error + Fatal + Panic + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Logger Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); + +use DBI; +use Carp; +use POSIX; +use IO::Handle; +use Data::Dumper; +use Time::HiRes qw/gettimeofday/; +use Sys::Syslog; + +use constant { + DEBUG => 1, + INFO => 0, + WARNING => -1, + ERROR => -2, + FATAL => -3, + PANIC => -4, + NOLOG => -5 +}; + +our %codes = ( + &DEBUG => "DBG", + &INFO => "INF", + &WARNING => "WAR", + &ERROR => "ERR", + &FATAL => "FAT", + &PANIC => "PNC", + &NOLOG => "OFF" +); + +our %priorities = ( + &DEBUG => "debug", + &INFO => "info", + &WARNING => "warning", + &ERROR => "err", + &FATAL => "err", + &PANIC => "err" +); + +our $logger; + +sub new +{ + my $class = shift; + my $this = {}; + + $this->{initialised} = undef; + + #$this->{id} = "zmundef"; + ( $this->{id} ) = $0 =~ m|^(?:.*/)?([^/]+?)(?:\.[^/.]+)?$|; + $this->{idRoot} = $this->{id}; + $this->{idArgs} = ""; + + $this->{level} = INFO; + $this->{termLevel} = NOLOG; + $this->{databaseLevel} = NOLOG; + $this->{fileLevel} = NOLOG; + $this->{syslogLevel} = NOLOG; + $this->{effectiveLevel} = INFO; + + $this->{autoFlush} = 1; + $this->{hasTerm} = -t STDERR; + + ( $this->{fileName} = $0 ) =~ s|^.*/||; + $this->{logPath} = ZM_PATH_LOGS; + $this->{logFile} = $this->{logPath}."/".$this->{id}.".log"; + + $this->{trace} = 0; + + bless( $this, $class ); + return $this; +} + +sub BEGIN +{ + # Fake the config variables that are used in case they are not defined yet + # Only really necessary to support upgrade from previous version + if ( !eval('defined(ZM_LOG_DEBUG)') ) + { + no strict 'subs'; + no strict 'refs'; + my %dbgConfig = ( + ZM_LOG_LEVEL_DATABASE => 0, + ZM_LOG_LEVEL_FILE => 0, + ZM_LOG_LEVEL_SYSLOG => 0, + ZM_LOG_DEBUG => 0, + ZM_LOG_DEBUG_TARGET => "", + ZM_LOG_DEBUG_LEVEL => 1, + ZM_LOG_DEBUG_FILE => "" + ); + while ( my ( $name, $value ) = each( %dbgConfig ) ) + { + *{$name} = sub { $value }; + } + use strict 'subs'; + use strict 'refs'; + } +} + +sub DESTROY +{ + my $this = shift; + $this->terminate(); +} + +sub initialise( @ ) +{ + my $this = shift; + my %options = @_; + + $this->{id} = $options{id} if ( defined($options{id}) ); + + $this->{logPath} = $options{logPath} if ( defined($options{logPath}) ); + + my $tempLogFile; + $tempLogFile = $this->{logPath}."/".$this->{id}.".log"; + $tempLogFile = $options{logFile} if ( defined($options{logFile}) ); + if ( my $logFile = $this->getTargettedEnv('LOG_FILE') ) + { + $tempLogFile = $logFile; + } + + my $tempLevel = INFO; + my $tempTermLevel = $this->{termLevel}; + my $tempDatabaseLevel = $this->{databaseLevel}; + my $tempFileLevel = $this->{fileLevel}; + my $tempSyslogLevel = $this->{syslogLevel}; + + $tempTermLevel = $options{termLevel} if ( defined($options{termLevel}) ); + if ( defined($options{databaseLevel}) ) + { + $tempDatabaseLevel = $options{databaseLevel}; + } + else + { + $tempDatabaseLevel = ZM_LOG_LEVEL_DATABASE; + } + if ( defined($options{fileLevel}) ) + { + $tempFileLevel = $options{fileLevel}; + } + else + { + $tempFileLevel = ZM_LOG_LEVEL_FILE; + } + if ( defined($options{syslogLevel}) ) + { + $tempSyslogLevel = $options{syslogLevel}; + } + else + { + $tempSyslogLevel = ZM_LOG_LEVEL_SYSLOG; + } + + if ( defined($ENV{'LOG_PRINT'}) ) + { + $tempTermLevel = $ENV{'LOG_PRINT'}? DEBUG : NOLOG; + } + + my $level; + $tempLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL')) ); + + $tempTermLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_TERM')) ); + $tempDatabaseLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_DATABASE')) ); + $tempFileLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_FILE')) ); + $tempSyslogLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')) ); + + if ( ZM_LOG_DEBUG ) + { + foreach my $target ( split( /\|/, ZM_LOG_DEBUG_TARGET ) ) + { + if ( $target eq $this->{id} || $target eq "_".$this->{id} || $target eq $this->{idRoot} || $target eq "_".$this->{idRoot} || $target eq "" ) + { + if ( ZM_LOG_DEBUG_LEVEL > NOLOG ) + { + $tempLevel = $this->limit( ZM_LOG_DEBUG_LEVEL ); + if ( ZM_LOG_DEBUG_FILE ne "" ) + { + $tempLogFile = ZM_LOG_DEBUG_FILE; + $tempFileLevel = $tempLevel; + } + } + } + } + } + + $this->logFile( $tempLogFile ); + + $this->termLevel( $tempTermLevel ); + $this->databaseLevel( $tempDatabaseLevel ); + $this->fileLevel( $tempFileLevel ); + $this->syslogLevel( $tempSyslogLevel ); + + $this->level( $tempLevel ); + + $this->{trace} = $options{trace} if ( defined($options{trace}) ); + + $this->{autoFlush} = $ENV{'LOG_FLUSH'}?1:0 if ( defined($ENV{'LOG_FLUSH'}) ); + + $this->{initialised} = !undef; + + Debug( "LogOpts: level=".$codes{$this->{level}}."/".$codes{$this->{effectiveLevel}}.", screen=".$codes{$this->{termLevel}}.", database=".$codes{$this->{databaseLevel}}.", logfile=".$codes{$this->{fileLevel}}."->".$this->{logFile}.", syslog=".$codes{$this->{syslogLevel}} ); +} + +sub terminate() +{ + my $this = shift; + return unless ( $this->{initialised} ); + $this->syslogLevel( NOLOG ); + $this->fileLevel( NOLOG ); + $this->databaseLevel( NOLOG ); + $this->termLevel( NOLOG ); +} + +sub reinitialise() +{ + my $this = shift; + + return unless ( $this->{initialised} ); + + # Bit of a nasty hack to reopen connections to log files and the DB + my $syslogLevel = $this->syslogLevel(); + $this->syslogLevel( NOLOG ); + my $logfileLevel = $this->fileLevel(); + $this->fileLevel( NOLOG ); + my $databaseLevel = $this->databaseLevel(); + $this->databaseLevel( NOLOG ); + my $screenLevel = $this->termLevel(); + $this->termLevel( NOLOG ); + + $this->syslogLevel( $syslogLevel ) if ( $syslogLevel > NOLOG ); + $this->fileLevel( $logfileLevel ) if ( $logfileLevel > NOLOG ); + $this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG ); + $this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG ); +} + +sub limit( $ ) +{ + my $this = shift; + my $level = shift; + return( DEBUG ) if ( $level > DEBUG ); + return( NOLOG ) if ( $level < NOLOG ); + return( $level ); +} + +sub getTargettedEnv( $ ) +{ + my $this = shift; + my $name = shift; + my $envName = $name."_".$this->{id}; + my $value; + $value = $ENV{$envName} if ( defined($ENV{$envName}) ); + if ( !defined($value) && $this->{id} ne $this->{idRoot} ) + { + $envName = $name."_".$this->{idRoot}; + $value = $ENV{$envName} if ( defined($ENV{$envName}) ); + } + if ( !defined($value) ) + { + $value = $ENV{$name} if ( defined($ENV{$name}) ); + } + if ( defined($value) ) + { + ( $value ) = $value =~ m/(.*)/; + } + return( $value ); +} + +sub fetch() +{ + if ( !$logger ) + { + $logger = ZoneMinder::Logger->new(); + $logger->initialise( 'syslogLevel'=>INFO, 'databaseLevel'=>INFO ); + } + return( $logger ); +} + +sub id( ;$ ) +{ + my $this = shift; + my $id = shift; + if ( defined($id) && $this->{id} ne $id ) + { + # Remove whitespace + $id =~ s/\S//g; + # Replace non-alphanum with underscore + $id =~ s/[^a-zA-Z_]/_/g; + + if ( $this->{id} ne $id ) + { + $this->{id} = $this->{idRoot} = $id; + if ( $id =~ /^([^_]+)_(.+)$/ ) + { + $this->{idRoot} = $1; + $this->{idArgs} = $2; + } + } + } + return( $this->{id} ); +} + +sub level( ;$ ) +{ + my $this = shift; + my $level = shift; + if ( defined($level) ) + { + $this->{level} = $this->limit( $level ); + $this->{effectiveLevel} = NOLOG; + $this->{effectiveLevel} = $this->{termLevel} if ( $this->{termLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{databaseLevel} if ( $this->{databaseLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{fileLevel} if ( $this->{fileLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{syslogLevel} if ( $this->{syslogLevel} > $this->{level} ); + $this->{effectiveLevel} = $this->{level} if ( $this->{effectiveLevel} > $this->{level} ); + } + return( $this->{level} ); +} + +sub debugOn() +{ + my $this = shift; + return( $this->{effectiveLevel} >= DEBUG ); +} + +sub trace( ;$ ) +{ + my $this = shift; + $this->{trace} = $_[0] if ( @_ ); + return( $this->{trace} ); +} + +sub termLevel( ;$ ) +{ + my $this = shift; + my $termLevel = shift; + if ( defined($termLevel) ) + { + $termLevel = NOLOG if ( !$this->{hasTerm} ); + $termLevel = $this->limit( $termLevel ); + if ( $this->{termLevel} != $termLevel ) + { + $this->{termLevel} = $termLevel; + } + } + return( $this->{termLevel} ); +} + +sub databaseLevel( ;$ ) +{ + my $this = shift; + my $databaseLevel = shift; + if ( defined($databaseLevel) ) + { + $databaseLevel = $this->limit( $databaseLevel ); + if ( $this->{databaseLevel} != $databaseLevel ) + { + if ( $databaseLevel > NOLOG && $this->{databaseLevel} <= NOLOG ) + { + if ( !$this->{dbh} ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + + if ( defined($port) ) + { + $this->{dbh} = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".$host.";port=".$port, ZM_DB_USER, ZM_DB_PASS ); + } + else + { + $this->{dbh} = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + } + if ( !$this->{dbh} ) + { + $databaseLevel = NOLOG; + Error( "Unable to write log entries to DB, can't connect to database '".ZM_DB_NAME."' on host '".ZM_DB_HOST."'" ); + } + else + { + $this->{dbh}->{AutoCommit} = 1; + Fatal( "Can't set AutoCommit on in database connection" ) unless( $this->{dbh}->{AutoCommit} ); + $this->{dbh}->{mysql_auto_reconnect} = 1; + Fatal( "Can't set mysql_auto_reconnect on in database connection" ) unless( $this->{dbh}->{mysql_auto_reconnect} ); + $this->{dbh}->trace( 0 ); + } + } + } + elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) + { + if ( $this->{dbh} ) + { + $this->{dbh}->disconnect(); + undef($this->{dbh}); + } + } + $this->{databaseLevel} = $databaseLevel; + } + } + return( $this->{databaseLevel} ); +} + +sub fileLevel( ;$ ) +{ + my $this = shift; + my $fileLevel = shift; + if ( defined($fileLevel) ) + { + $fileLevel = $this->limit($fileLevel); + if ( $this->{fileLevel} != $fileLevel ) + { + $this->closeFile() if ( $this->{fileLevel} > NOLOG ); + $this->{fileLevel} = $fileLevel; + $this->openFile() if ( $this->{fileLevel} > NOLOG ); + } + } + return( $this->{fileLevel} ); +} + +sub syslogLevel( ;$ ) +{ + my $this = shift; + my $syslogLevel = shift; + if ( defined($syslogLevel) ) + { + $syslogLevel = $this->limit($syslogLevel); + if ( $this->{syslogLevel} != $syslogLevel ) + { + $this->closeSyslog() if ( $syslogLevel <= NOLOG && $this->{syslogLevel} > NOLOG ); + $this->openSyslog() if ( $syslogLevel > NOLOG && $this->{syslogLevel} <= NOLOG ); + $this->{syslogLevel} = $syslogLevel; + } + } + return( $this->{syslogLevel} ); +} + +sub openSyslog() +{ + my $this = shift; + openlog( $this->{id}, "pid", "local1" ); +} + +sub closeSyslog() +{ + my $this = shift; + #closelog(); +} + +sub logFile( $ ) +{ + my $this = shift; + my $logFile = shift; + if ( $logFile =~ /^(.+)\+$/ ) + { + $this->{logFile} = $1.'.'.$$; + } + else + { + $this->{logFile} = $logFile; + } +} + +sub openFile() +{ + my $this = shift; + if ( open( LOGFILE, ">>".$this->{logFile} ) ) + { + LOGFILE->autoflush() if ( $this->{autoFlush} ); + + my $webUid = (getpwnam( ZM_WEB_USER ))[2]; + my $webGid = (getgrnam( ZM_WEB_GROUP ))[2]; + if ( $> == 0 ) + { + chown( $webUid, $webGid, $this->{logFile} ) or Fatal( "Can't change permissions on log file '".$this->{logFile}."': $!" ) + } + } + else + { + $this->fileLevel( NOLOG ); + Error( "Can't open log file '".$this->{logFile}."': $!" ); + } +} + +sub closeFile() +{ + my $this = shift; + close( LOGFILE ) if ( fileno(LOGFILE) ); +} + +sub logPrint( $;$ ) +{ + my $this = shift; + my $level = shift; + my $string = shift; + + if ( $level <= $this->{effectiveLevel} ) + { + $string =~ s/[\r\n]+$//g; + + my $code = $codes{$level}; + + my ($seconds, $microseconds) = gettimeofday(); + my $message = sprintf( "%s.%06d %s[%d].%s [%s]", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $this->{id}, $$, $code, $string ); + if ( $this->{trace} ) + { + $message = Carp::shortmess( $message ); + } + else + { + $message = $message."\n"; + } + syslog( $priorities{$level}, $code." [%s]", $string ) if ( $level <= $this->{syslogLevel} ); + print( LOGFILE $message ) if ( $level <= $this->{fileLevel} ); + if ( $level <= $this->{databaseLevel} ) + { + my $sql = "insert into Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, NULL )"; + $this->{sth} = $this->{dbh}->prepare_cached( $sql ); + if ( !$this->{sth} ) + { + $this->{databaseLevel} = NOLOG; + Fatal( "Can't prepare log entry '$sql': ".$this->{dbh}->errstr() ); + } + my $res = $this->{sth}->execute( $seconds+($microseconds/1000000.0), $this->{id}, $$, $level, $code, $string, $this->{fileName} ); + if ( !$res ) + { + $this->{databaseLevel} = NOLOG; + Fatal( "Can't execute log entry '$sql': ".$this->{sth}->errstr() ); + } + } + print( STDERR $message ) if ( $level <= $this->{termLevel} ); + } +} + +sub logInit( ;@ ) +{ + my %options = @_ ? @_ : (); + $logger = ZoneMinder::Logger->new() if ( !$logger ); + $logger->initialise( %options ); +} + +sub logReinit() +{ + fetch()->reinitialise(); +} + +sub logTerm +{ + return unless ( $logger ); + $logger->terminate(); + $logger = undef; +} + +sub logHupHandler() +{ + my $savedErrno = $!; + return unless( $logger ); + fetch()->reinitialise(); + logSetSignal(); + $! = $savedErrno; +} + +sub logSetSignal() +{ + $SIG{HUP} = \&logHupHandler; +} + +sub logClearSignal() +{ + $SIG{HUP} = 'DEFAULT'; +} + +sub logLevel( ;$ ) +{ + return( fetch()->level( @_ ) ); +} + +sub logDebugging() +{ + return( fetch()->debugOn() ); +} + +sub logTermLevel( ;$ ) +{ + return( fetch()->termLevel( @_ ) ); +} + +sub logDatabaseLevel( ;$ ) +{ + return( fetch()->databaseLevel( @_ ) ); +} + +sub logFileLevel( ;$ ) +{ + return( fetch()->fileLevel( @_ ) ); +} + +sub logSyslogLevel( ;$ ) +{ + return( fetch()->syslogLevel( @_ ) ); +} + +sub Mark( ;$$ ) +{ + my $level = shift; + $level = DEBUG unless( defined($level) ); + my $tag = "Mark"; + fetch()->logPrint( $level, $tag ); +} + +sub Dump( \$;$ ) +{ + my $var = shift; + my $label = shift; + $label = "VAR" unless( defined($label) ); + fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) ); +} + +sub Debug( @ ) +{ + fetch()->logPrint( DEBUG, @_ ); +} + +sub Info( @ ) +{ + fetch()->logPrint( INFO, @_ ); +} + +sub Warning( @ ) +{ + fetch()->logPrint( WARNING, @_ ); +} + +sub Error( @ ) +{ + fetch()->logPrint( ERROR, @_ ); +} + +sub Fatal( @ ) +{ + fetch()->logPrint( FATAL, @_ ); + exit( -1 ); +} + +sub Panic( @ ) +{ + fetch()->logPrint( PANIC, @_ ); + confess( $_[0] ); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::Logger - ZoneMinder Logger module + +=head1 SYNOPSIS + + use ZoneMinder::Logger; + use ZoneMinder::Logger qw(:all); + + logInit( "myproc", DEBUG ); + + Debug( "This is what is happening" ); + Info( "Something interesting is happening" ); + Warning( "Something might be going wrong." ); + Error( "Something has gone wrong!!" ); + Fatal( "Something has gone badly wrong, gotta stop!!" ); + Panic( "Something fundamental has gone wrong, die with stack trace ); + +=head1 DESCRIPTION + +The ZoneMinder:Logger module contains the common debug and error reporting routines used by the ZoneMinder scripts. + +To use debug in your scripts you need to include this module, and call logInit. Thereafter you can sprinkle Debug or Error calls etc throughout the code safe in the knowledge that they will be reported to your error log, and possibly the syslogger, in a meaningful and consistent format. + +Debug is discussed in terms of levels where 1 and above (currently only 1 for scripts) is considered debug, 0 is considered as informational, -1 is a warning, -2 is an error and -3 is a fatal error or panic. Where levels are mentioned below as thresholds the value given and anything with a lower level (ie. more serious) will be included. + +=head1 METHODS + +=over 4 + +=item logInit ( $id, %options ); + +Initialises the debug and prepares the logging for forthcoming operations. If not called explicitly it will be called by the first debug call in your script, but with default (and probably meaningless) options. The only compulsory arguments are $id which must be a string that will identify debug coming from this script in mixed logs. Other options may be provided as below, + + Option Default Description + --------- --------- ----------- + level INFO The initial debug level which defines which statements are output and which are ignored + trace 0 Whether to use the Carp::shortmess format in debug statements to identify where the debug was emitted from + termLevel NOLOG At what level debug is written to terminal standard error, 0 is no, 1 is yes, 2 is write only if terminal + databaseLevel INFO At what level debug is written to the Log table in the database; + fileLevel NOLOG At what level debug is written to a log file of the format of .log in the standard log directory. + syslogLevel INFO At what level debug is written to syslog. + +To disable any of these action entirely set to NOLOG + +=item logTerm (); + +Used to end the debug session and close any logs etc. Not usually necessary. + +=item $id = logId ( [$id] ); + +=item $level = logLevel ( [$level] ); + +=item $trace = logTrace ( [$trace] ); + +=item $level = logLevel ( [$level] ); + +=item $termLevel = logTermLevel ( [$termLevel] ); + +=item $databaseLevel = logDatabaseLevel ( [$databaseLevel] ); + +=item $fileLevel = logFileLevel ( [$fileLevel] ); + +=item $syslogLevel = logSyslogLevel ( [$syslogLevel] ); + +These methods can be used to get and set the current settings as defined in logInit. + +=item Debug( $string ); + +This method will output a debug message if the current debug level permits it, otherwise does nothing. This message will be tagged with the DBG string in the logs. + +=item Info( $string ); + +This method will output an informational message if the current debug level permits it, otherwise does nothing. This message will be tagged with the INF string in the logs. + +=item Warning( $string ); + +This method will output a warning message if the current debug level permits it, otherwise does nothing. This message will be tagged with the WAR string in the logs. + +=item Error( $string ); + +This method will output an error message if the current debug level permits it, otherwise does nothing. This message will be tagged with the ERR string in the logs. + +=item Fatal( $string ); + +This method will output a fatal error message and then die if the current debug level permits it, otherwise does nothing. This message will be tagged with the FAT string in the logs. + +=item Panic( $string ); + +This method will output a panic error message and then die with a stack trace if the current debug level permits it, otherwise does nothing. This message will be tagged with the PNC string in the logs. + +=head2 EXPORT + +None by default. +The :constants tag will export the debug constants which define the various levels of debug +The :variables tag will export variables containing the current debug id and level +The :functions tag will export the debug functions. This or :all is what you would normally use. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +Carp +Sys::Syslog + +The ZoneMinder README file Troubleshooting section for an extended discussion on the use and configuration of syslog with ZoneMinder. + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory.pm new file mode 100644 index 000000000..86037713d --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory.pm @@ -0,0 +1,873 @@ +# ========================================================================== +# +# ZoneMinder Memory Access Module, $Date: 2008-02-25 10:13:13 +0000 (Mon, 25 Feb 2008) $, $Revision: 2323 $ +# 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::Memory; + +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 = ( + 'constants' => [ qw( + STATE_IDLE + STATE_PREALARM + STATE_ALARM + STATE_ALERT + STATE_TAPE + ACTION_GET + ACTION_SET + ACTION_RELOAD + ACTION_SUSPEND + ACTION_RESUME + TRIGGER_CANCEL + TRIGGER_ON + TRIGGER_OFF + ) ], + 'functions' => [ qw( + zmMemVerify + zmMemInvalidate + zmMemRead + zmMemWrite + zmMemTidy + zmGetMonitorState + zmGetAlarmLocation + zmIsAlarmed + zmInAlarm + zmHasAlarmed + zmGetLastEvent + zmGetLastWriteTime + zmGetLastReadTime + zmMonitorEnable + zmMonitorDisable + zmMonitorSuspend + zmMonitorResume + zmTriggerEventOn + zmTriggerEventOff + zmTriggerEventCancel + zmTriggerShowtext + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Shared Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +use constant STATE_IDLE => 0; +use constant STATE_PREALARM => 1; +use constant STATE_ALARM => 2; +use constant STATE_ALERT => 3; +use constant STATE_TAPE => 4; + +use constant ACTION_GET => 1; +use constant ACTION_SET => 2; +use constant ACTION_RELOAD => 4; +use constant ACTION_SUSPEND => 16; +use constant ACTION_RESUME => 32; + +use constant TRIGGER_CANCEL => 0; +use constant TRIGGER_ON => 1; +use constant TRIGGER_OFF => 2; + +use Storable qw( freeze thaw ); + +if ( "yes" eq 'yes' ) # 'yes' if memory is mmapped +{ + require ZoneMinder::Memory::Mapped; + ZoneMinder::Memory::Mapped->import(); +} +else +{ + require ZoneMinder::Memory::Shared; + ZoneMinder::Memory::Shared->import(); +} + +# Native architecture +our $arch = int(3.2*length(~0)); +our $native = $arch/8; +our $mem_seq = 0; + +our $mem_data = +{ + "shared_data" => { "type"=>"SharedData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_read_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_event" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "action" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "brightness" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "hue" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "colour" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "contrast" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "valid" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "active" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "signal" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "format" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "imagesize" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "control_state" => { "type"=>"uint8[256]", "seq"=>$mem_seq++ }, + } + }, + "trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "padding" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_cause" => { "type"=>"int8[32]", "seq"=>$mem_seq++ }, + "trigger_text" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + "trigger_showtext" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + } + }, + "end" => { "seq"=>$mem_seq++, "size"=> 0 } +}; + +our $mem_size = 0; +our $mem_verified = {}; + +sub zmMemInit +{ + my $offset = 0; + + foreach my $section_data ( sort { $a->{seq} <=> $b->{seq} } values( %$mem_data ) ) + { + $section_data->{offset} = $offset; + $section_data->{align} = 0; + + if ( $section_data->{align} > 1 ) + { + my $rem = $offset % $section_data->{align}; + if ( $rem > 0 ) + { + $offset += ($section_data->{align} - $rem); + } + } + foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) ) + { + if ( $member_data->{type} eq "long" || $member_data->{type} eq "ulong" || $member_data->{type} eq "size_t") + { + $member_data->{size} = $member_data->{align} = $native; + } + elsif( $member_data->{type} eq "int64" || $member_data->{type} eq "uint64" || $member_data->{type} eq "time_t64") + { + $member_data->{size} = $member_data->{align} = 8; + } + elsif ( $member_data->{type} eq "int32" || $member_data->{type} eq "uint32" || $member_data->{type} eq "bool4" ) + { + $member_data->{size} = $member_data->{align} = 4; + } + elsif ($member_data->{type} eq "int16" || $member_data->{type} eq "uint16") + { + $member_data->{size} = $member_data->{align} = 2; + } + elsif ( $member_data->{type} eq "int8" || $member_data->{type} eq "uint8" || $member_data->{type} eq "bool1" ) + { + $member_data->{size} = $member_data->{align} = 1; + } + elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) + { + $member_data->{size} = $1; + $member_data->{align} = 1; + } + else + { + Fatal( "Unexpected type '".$member_data->{type}."' found in shared data definition." ); + } + + if ( $member_data->{align} > 1 && ($offset%$member_data->{align}) > 0 ) + { + $offset += ($member_data->{align} - ($offset%$member_data->{align})); + } + $member_data->{offset} = $offset; + $offset += $member_data->{size} + } + $section_data->{size} = $offset - $section_data->{offset}; + } + + $mem_size = $offset; +} + +&zmMemInit(); + +sub zmMemVerify( $ ) +{ + my $monitor = shift; + if ( !zmMemAttach( $monitor, $mem_size ) ) + { + return( undef ); + } + + my $mem_key = zmMemKey( $monitor ); + if ( !defined($mem_verified->{$mem_key}) ) + { + my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); + if ( $sd_size != $mem_data->{shared_data}->{size} ) + { + if ( $sd_size ) + { + Error( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + else + { + Debug( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + return( undef ); + } + my $td_size = zmMemRead( $monitor, "trigger_data:size", 1 ); + if ( $td_size != $mem_data->{trigger_data}->{size} ) + { + if ( $td_size ) + { + Error( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + else + { + Debug( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + return( undef ); + } + $mem_verified->{$mem_key} = !undef; + } + return( !undef ); +} + +sub zmMemRead( $$;$ ) +{ + my $monitor = shift; + my $fields = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + if ( !ref($fields) ) + { + $fields = [ $fields ]; + } + my @values; + foreach my $field ( @$fields ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data = zmMemGet( $monitor, $offset, $size ); + if ( !defined($data) ) + { + Error( "Unable to read '$field' from memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + my $value; + if ( $type eq "long" ) + { + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int32" ) + { + ( $value ) = unpack( "l", $data ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + ( $value ) = unpack( "L", $data ); + } + elsif ( $type eq "int16" ) + { + ( $value ) = unpack( "s", $data ); + } + elsif ( $type eq "uint16" ) + { + ( $value ) = unpack( "S", $data ); + } + elsif ( $type eq "int8" ) + { + ( $value ) = unpack( "c", $data ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + ( $value ) = unpack( "C", $data ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + ( $value ) = unpack( "Z".$size, $data ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + ( $value ) = unpack( "C".$size, $data ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + push( @values, $value ); + } + if ( wantarray() ) + { + return( @values ) + } + return( $values[0] ); +} + +sub zmMemInvalidate( $ ) +{ + my $monitor = shift; + my $mem_key = zmMemKey($monitor); + if ( $mem_key ) + { + delete $mem_verified->{$mem_key}; + zmMemDetach( $monitor ); + } +} + +sub zmMemTidy() +{ + zmMemClean(); +} + +sub zmMemWrite( $$;$ ) +{ + my $monitor = shift; + my $field_values = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + while ( my ( $field, $value ) = each( %$field_values ) ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data; + if ( $type eq "long" ) + { + $data = pack( "l!", $value ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + $data = pack( "L!", $value ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "l!", $value ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "L!", $value ); + } + elsif ( $type eq "int32" ) + { + $data = pack( "l", $value ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + $data = pack( "L", $value ); + } + elsif ( $type eq "int16" ) + { + $data = pack( "s", $value ); + } + elsif ( $type eq "uint16" ) + { + $data = pack( "S", $value ); + } + elsif ( $type eq "int8" ) + { + $data = pack( "c", $value ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + $data = pack( "C", $value ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + $data = pack( "Z".$size, $value ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + $data = pack( "C".$size, $value ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + + if ( !zmMemPut( $monitor, $offset, $size, $data ) ) + { + Error( "Unable to write '$value' to '$field' in memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + } + return( !undef ); +} + +sub zmGetMonitorState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:state" ) ); +} + +sub zmGetAlarmLocation( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, [ "shared_data:alarm_x", "shared_data:alarm_y" ] ) ); +} + +sub zmSetControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmMemWrite( $monitor, { "shared_data:control_state" => $control_state } ); +} + +sub zmGetControlState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:control_state" ) ); +} + +sub zmSaveControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmSetControlState( $monitor, freeze( $control_state ) ); +} + +sub zmRestoreControlState( $ ) +{ + my $monitor = shift; + + return( thaw( zmGetControlState( $monitor ) ) ); +} + +sub zmIsAlarmed( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM ); +} + +sub zmInAlarm( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM || $state == STATE_ALERT ); +} + +sub zmHasAlarmed( $$ ) +{ + my $monitor = shift; + my $last_event_id = shift; + + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] ); + + if ( $state == STATE_ALARM || $state == STATE_ALERT ) + { + return( $last_event ); + } + elsif( $last_event != $last_event_id ) + { + return( $last_event ); + } + return( undef ); +} + +sub zmGetLastEvent( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_event" ) ); +} + +sub zmGetLastWriteTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_write_time" ) ); +} + +sub zmGetLastReadTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_read_time" ) ); +} + +sub zmGetMonitorActions( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:action" ) ); +} + +sub zmMonitorEnable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorDisable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorSuspend( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorResume( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmGetTriggerState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "trigger_data:trigger_state" ) ); +} + +sub zmTriggerEventOn( $$$;$$ ) +{ + my $monitor = shift; + my $score = shift; + my $cause = shift; + my $text = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_score" => $score, + "trigger_data:trigger_cause" => $cause, + }; + $values->{"trigger_data:trigger_text"} = $text if ( defined($text) ); + $values->{"trigger_data:trigger_showtext"} = $showtext if ( defined($showtext) ); + $values->{"trigger_data:trigger_state"} = TRIGGER_ON; # Write state last so event not read incomplete + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventOff( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_OFF, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventCancel( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_CANCEL, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerShowtext( $$ ) +{ + my $monitor = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_showtext" => $showtext, + }; + + zmMemWrite( $monitor, $values ); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::MappedMem - ZoneMinder Mapped Memory access module + +=head1 SYNOPSIS + + use ZoneMinder::MappedMem; + use ZoneMinder::MappedMem qw(:all); + + if ( zmMemVerify( $monitor ) ) + { + $state = zmGetMonitorState( $monitor ); + if ( $state == STATE_ALARM ) + { + ... + } + } + + ( $lri, $lwi ) = zmMemRead( $monitor, [ "shared_data:last_read_index", "shared_data:last_write_index" ] ); + zmMemWrite( $monitor, { "trigger_data:trigger_showtext" => "Some Text" } ); + +=head1 DESCRIPTION + +The ZoneMinder:MappedMem module contains methods for accessing and writing to mapped memory as well as helper methods for common operations. + +The core elements of ZoneMinder used mapped memory to allow multiple access to resources. Although ZoneMinder scripts have used this information before, up until now it was difficult to access and prone to errors. This module introduces a common API for mapped memory access (both reading and writing) making it a lot easier to customise scripts or even create your own. + +All the methods listed below require a 'monitor' parameter. This must be a reference to a hash with at least the 'Id' field set to the monitor id of the mapped memory you wish to access. Using database methods to select the monitor details will also return this kind of data. Some of the mapped memory methods will add and amend new fields to this hash. + +=over 4 + +=head1 METHODS + +=item zmMemVerify ( $monitor ); + +Verify that the mapped memory of the monitor given exists and is valid. It will return an undefined value if it is not valid. You should generally call this method first before using any of the other methods, but most of the remaining methods will also do so if the memory has not already been verified. + +=item zmMemInvalidate ( $monitor ); + +Following an error, reset the mapped memory ids and attempt to reverify on the next operation. This is mostly used when a mapped memory segment has gone away and been recreated with a different id. + +=item zmMemRead ( $monitor, $readspec ); + +This method is used to read data from mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'readspec' must either be a string of the form "

:" or a reference to an array of strings of the same format. In the first case a single value is returned, in the latter case a list of values is return. Errors will cause undefined to be returned. The allowable sections and field names are described below. + +=item zmMemWrite ( $monitor, $writespec ); + +This method is used to write data to mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'writespec' must be a reference to a hash with keys of the form "
:" and values as the data to be written. Errors will cause undefined to be returned, otherwise a non-undefined value will be returned. The allowable sections and field names are described below. + +=item $state = zmGetMonitorState ( $monitor ); + +Return the current state of the given monitor. This is an integer value and can be compared with the STATE constants given below. + +=item $event_id = zmGetLastEvent ( $monitor ); + +Return the event id of the last event that the monitor generated, or 0 if no event has been generated by the current monitor process. + +=item zmIsAlarmed ( $monitor ); + +Return 1 if the monitor given is currently in an alarm state, 0 otherwise. + +=item zmInAlarm ( $monitor ); + +Return 1 if the monitor given is currently in an alarm or alerted state, 0 otherwise. + +=item zmHasAlarmed ( $monitor ); + +Return 1 if the given monitor is in an alarm state, or has been in an alarm state since the last call to this method. + +=item ( $x, $y ) = zmGetAlarmLocation ( $monitor ); + +Return an x,y pair indicating the image co-ordinates of the centre of the last motion event generated by the given monitor. If no event has been generated by the current monitor process, or the alarm was not motion related, returns -1,-1. + +=item zmGetLastWriteTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was captured by the given monitor and written to shared memory, or 0 otherwise. + +=item zmGetLastReadTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was read from shared memory by the analysis daemon of the given monitor, or 0 otherwise or if the monitor is in monitor only mode. + +=item zmMonitorSuspend ( $monitor ); + +Suspend the given monitor from generating events caused by motion. This method can be used to prevent camera actions such as panning or zooming from causing events. If configured to do so, the monitor may automatically resume after a defined period. + +=item zmMonitorResume ( $monitor ); + +Allow the given monitor to resume generating events caused by motion. + +=item zmTriggerEventOn ( $monitor, $score, $cause [, $text, $showtext ] ); + +Trigger the given monitor to generate an event. You must supply an event score and a cause string indicating the reason for the event. You may also supply a text string containing further details about the event and a showtext string which may be included in the timestamp annotation on any images captured during the event, if configured to do so. + +=item zmTriggerEventOff ( $monitor ); + +Trigger the given monitor to not generate any events. This method does not cancel zmTriggerEventOn, but is exclusive to it. This method is intended to allow external triggers to prevent normal events being generated by monitors in the same way as zmMonitorSuspend but applies to all events and not just motion, and is intended for longer timescales than are appropriate for suspension. + +=item zmTriggerEventCancel ( $monitor ); + +Cancel any previous trigger on or off requests. This stops a triggered alarm if it exists from a previous 'on' and allows events to be generated once more following a previous 'off'. + +=item zmTriggerShowtext ( $monitor, $showtest ); + +Indicate that the given text should be displayed in the timestamp annotation on any images captured, if the format of the annotation string defined for the monitor permits. + +=head1 DATA + +The data fields in mapped memory that may be accessed are as follows. There are two main sections, shared_data which is general data and trigger_data which is used for event triggering. Whilst reading from these fields is harmless, extreme care must be taken when writing to mapped memory, especially in the shared_data section as this is normally written to only by monitor capture and analysis processes. + + shared_data The general mapped memory section + size The size, in bytes, of this section + valid Flag indicating whether this section has been initialised + active Flag indicating whether this monitor is active (enabled/disabled) + signal Flag indicating whether this monitor is reciving a valid signal + state The current monitor state, see the STATE constants below + last_write_index The last index, in the image buffer, that an image has been saved to + last_read_index The last index, in the image buffer, that an image has been analysed from + last_write_time The time (in utc seconds) when the last image was captured + last_read_time The time (in utc seconds) when the last image was analysed + last_event The id of the last event generated by the monitor analysis process, 0 if none + action The monitor actions bitmask, see the ACTION constants below + brightness Read/write location for the current monitor brightness + hue Read/write location for the current monitor hue + colour Read/write location for the current monitor colour + contrast Read/write location for the current monitor contrast + alarm_x Image x co-ordinate (from left) of the centre of the last motion event, -1 if none + alarm_y Image y co-ordinate (from top) of the centre of the last motion event, -1 if none + + trigger_data The triggered event mapped memory section + size The size, in bytes of this section + trigger_state The current trigger state, see the TRIGGER constants below + trigger_score The current triggered event score + trigger_cause The current triggered event cause string + trigger_text The current triggered event descriptive text string + trigger_showtext The triggered text that will be displayed on captured image timestamps + +=head1 CONSTANTS + +The following constants are used by the methods above, but can also be used by user scripts if required. + +=item STATE_IDLE STATE_PREALARM STATE_ALARM STATE_ALERT STATE_TAPE + +These constants define the state of the monitor with respect to alarms and events. They are used in the shared_data:state field. + +=item ACTION_GET ACTION_SET ACTION_RELOAD ACTION_SUSPEND ACTION_RESUME + +These constants defines the various values that can exist in the shared_data:action field. This is a bitmask which when non-zero defines an action that an executing monitor process should take. ACTION_GET requires that the current values of brightness, contrast, colour and hue are taken from the camera and written to the equivalent mapped memory fields. ACTION_SET implies the reverse, that the values in mapped memory should be written to the camera. ACTION_RELOAD signal that the monitor process should reload itself from the database in case any settings have changed there. ACTION_SUSPEND signals that a monitor should stop exaiming images for motion, though other alarms may still occur. ACTION_RESUME sigansl that a monitor should resume motion detectiom. + +=item TRIGGER_CANCEL TRIGGER_ON TRIGGER_OFF + +These constants are used in the definition of external triggers. TRIGGER_CANCEL is used to indicated that any previous trigger settings should be cancelled, TRIGGER_ON signals that an alarm should be created (or continued)) as a result of the current trigger and TRIGGER_OFF signals that the trigger should prevent any alarms from being generated. See the trigger methods above for further details. + +=head1 EXPORT + +None by default. +The :constants tag will export the mapped memory constants which mostly define enumerations for the variables held in memory +The :functions tag will export the mapped memory access functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Mapped.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Mapped.pm new file mode 100644 index 000000000..b8745d835 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Mapped.pm @@ -0,0 +1,169 @@ +# ========================================================================== +# +# ZoneMinder Mapped Memory Access Module, $Date: 2008-02-25 10:13:13 +0000 (Mon, 25 Feb 2008) $, $Revision: 2323 $ +# 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 definitions and functions used when accessing mapped memory +# +package ZoneMinder::Memory::Mapped; + +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( + zmMemKey + zmMemAttach + zmMemDetach + zmMemGet + zmMemPut + zmMemClean + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = @EXPORT_OK; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Mapped Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +use Sys::Mmap; + +sub zmMemKey( $ ) +{ + my $monitor = shift; + return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef ); +} + +sub zmMemAttach( $$ ) +{ + my $monitor = shift; + my $size = shift; + if ( !defined($monitor->{MMapAddr}) ) + { + my $mmap_file = ZM_PATH_MAP."/zm.mmap.".$monitor->{Id}; + if ( !open( MMAP, "+<".$mmap_file ) ) + { + Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) ); + return( undef ); + } + my $mmap = undef; + my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, \*MMAP ); + if ( !$mmap_addr || !$mmap ) + { + Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) ); + return( undef ); + } + $monitor->{MMapHandle} = \*MMAP; + $monitor->{MMapAddr} = $mmap_addr; + $monitor->{MMap} = \$mmap; + } + return( !undef ); +} + +sub zmMemDetach( $ ) +{ + my $monitor = shift; + + if ( $monitor->{MMap} ) + { + munmap( ${$monitor->{MMap}} ); + delete $monitor->{MMap}; + } + if ( $monitor->{MMapAddr} ) + { + delete $monitor->{MMapAddr}; + } + if ( $monitor->{MMapHandle} ) + { + close( $monitor->{MMapHandle} ); + delete $monitor->{MMapHandle}; + } +} + +sub zmMemGet( $$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + + my $mmap = $monitor->{MMap}; + if ( !$mmap || !$$mmap ) + { + Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?", $monitor->{Id} ) ); + return( undef ); + } + my $data = substr( $$mmap, $offset, $size ); + return( $data ); +} + +sub zmMemPut( $$$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + my $data = shift; + + my $mmap = $monitor->{MMap}; + if ( !$mmap || !$$mmap ) + { + Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?", $monitor->{Id} ) ); + return( undef ); + } + substr( $$mmap, $offset, $size ) = $data; + return( !undef ); +} + +sub zmMemClean +{ + Debug( "Removing memory map files\n" ); + my $mapPath = ZM_PATH_MAP."/zm.mmap.*"; + foreach my $mapFile( glob( $mapPath ) ) + { + ( $mapFile ) = $mapFile =~ /^(.+)$/; + Debug( "Removing memory map file '$mapFile'\n" ); + unlink( $mapFile ); + } +} + +1; +__END__ diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Shared.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Shared.pm new file mode 100644 index 000000000..c04e4f413 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Memory/Shared.pm @@ -0,0 +1,161 @@ +# ========================================================================== +# +# ZoneMinder Shared Memory Access Module, $Date: 2007-08-29 19:11:09 +0100 (Wed, 29 Aug 2007) $, $Revision: 2175 $ +# 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::Memory::Shared; + +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( + zmMemKey + zmMemAttach + zmMemDetach + zmMemGet + zmMemPut + zmMemClean + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = @EXPORT_OK; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Shared Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +sub zmMemKey( $ ) +{ + my $monitor = shift; + return( defined($monitor->{ShmKey})?$monitor->{ShmKey}:undef ); +} + +sub zmMemAttach( $$ ) +{ + my $monitor = shift; + my $size = shift; + if ( !defined($monitor->{ShmId}) ) + { + my $shm_key = (hex(ZM_SHM_KEY)&0xffff0000)|$monitor->{Id}; + my $shm_id = shmget( $shm_key, $size, 0 ); + if ( !defined($shm_id) ) + { + Error( sprintf( "Can't get shared memory id '%x', %d: $!\n", $shm_key, $monitor->{Id} ) ); + return( undef ); + } + $monitor->{ShmKey} = $shm_key; + $monitor->{ShmId} = $shm_id; + } + return( !undef ); +} + +sub zmMemDetach( $ ) +{ + my $monitor = shift; + + delete $monitor->{ShmId}; +} + +sub zmMemGet( $$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + + my $shm_key = $monitor->{ShmKey}; + my $shm_id = $monitor->{ShmId}; + + my $data; + if ( !shmread( $shm_id, $data, $offset, $size ) ) + { + Error( sprintf( "Can't read from shared memory '%x/%d': $!", $shm_key, $shm_id ) ); + return( undef ); + } + return( $data ); +} + +sub zmMemPut( $$$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + my $data = shift; + + my $shm_key = $monitor->{ShmKey}; + my $shm_id = $monitor->{ShmId}; + + if ( !shmwrite( $shm_id, $data, $offset, $size ) ) + { + Error( sprintf( "Can't write to shared memory '%x/%d': $!", $shm_key, $shm_id ) ); + return( undef ); + } + return( !undef ); +} + +sub zmMemClean +{ + Debug( "Removing shared memory\n" ); + # Find ZoneMinder shared memory + my $command = "ipcs -m | grep '^".substr( sprintf( "0x%x", hex(ZM_SHM_KEY) ), 0, -2 )."'"; + Debug( "Checking for shared memory with '$command'\n" ); + open( CMD, "$command |" ) or Fatal( "Can't execute '$command': $!" ); + while( ) + { + chomp; + my ( $key, $id ) = split( /\s+/ ); + if ( $id =~ /^(\d+)/ ) + { + $id = $1; + $command = "ipcrm shm $id"; + Debug( "Removing shared memory with '$command'\n" ); + qx( $command ); + } + } + close( CMD ); +} + +1; +__END__ diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel.pm new file mode 100644 index 000000000..0344e6d94 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel.pm @@ -0,0 +1,166 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel 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 base class definition of the trigger channel +# class tree +# +package ZoneMinder::Trigger::Channel; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Database Access +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my $self = {}; + $self->{readable} = !undef; + $self->{writeable} = !undef; + $self->{selectable} = undef; + $self->{state} = 'closed'; + bless( $self, $class ); + return $self; +} + +sub clone +{ + my $self = shift; + my $clone = { %$self }; + bless $clone, ref $self; +} + +sub open() +{ + my $self = shift; + my $class = ref($self) or croak( "Can't get class for non object $self" ); + croak( "Abstract base class method called for object of class $class" ); +} + +sub close() +{ + my $self = shift; + my $class = ref($self) or croak( "Can't get class for non object $self" ); + croak( "Abstract base class method called for object of class $class" ); +} + +sub getState() +{ + my $self = shift; + return( $self->{state} ); +} + +sub isOpen() +{ + my $self = shift; + return( $self->{state} eq "open" ); +} + +sub isConnected() +{ + my $self = shift; + return( $self->{state} eq "connected" ); +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( !exists($self->{$name}) ) + { + croak( "Can't access $name member of object of class $class" ); + } + return( $self->{$name} ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/File.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/File.pm new file mode 100644 index 000000000..234dae3d7 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/File.pm @@ -0,0 +1,121 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the simple file based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::File; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Handle; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Handle); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Simple file based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Fcntl; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel::Handle->new; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + #sysopen( *sfh, $conn->{path}, O_NONBLOCK|O_RDONLY ) or croak( "Can't sysopen: $!" ); + #open( *sfh, "<".$conn->{path} ) or croak( "Can't open: $!" ); + open( *sfh, "+<".$self->{path} ) or croak( "Can't open: $!" ); + $self->{state} = 'open'; + $self->{handle} = *sfh; +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Handle.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Handle.pm new file mode 100644 index 000000000..356bb5aea --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Handle.pm @@ -0,0 +1,154 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the handle based trigger channel +# class +# +package ZoneMinder::Trigger::Channel::Handle; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel; + +our @ISA = qw(ZoneMinder::Trigger::Channel); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base class for handle based trigger channels +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use POSIX; + +sub new +{ + my $class = shift; + my $port = shift; + my $self = ZoneMinder::Trigger::Channel->new(); + $self->{handle} = undef; + bless( $self, $class ); + return $self; +} + +sub spawns +{ + return( undef ); +} + +sub close() +{ + my $self = shift; + close( $self->{handle} ); + $self->{state} = 'closed'; + $self->{handle} = undef; +} + +sub read() +{ + my $self = shift; + my $buffer; + my $nbytes = sysread( $self->{handle}, $buffer, POSIX::BUFSIZ ); + if ( !$nbytes ) + { + return( undef ); + } + Debug( "Read '$buffer' ($nbytes bytes)\n" ); + return( $buffer ); +} + +sub write() +{ + my $self = shift; + my $buffer = shift; + my $nbytes = syswrite( $self->{handle}, $buffer ); + if ( !defined( $nbytes) || $nbytes < length($buffer) ) + { + Error( "Unable to write buffer '".$buffer.", expected ".length($buffer)." bytes, sent ".$nbytes.": $!\n" ); + return( undef ); + } + Debug( "Wrote '$buffer' ($nbytes bytes)\n" ); + return( !undef ); +} + +sub fileno() +{ + my $self = shift; + return( defined($self->{handle})?fileno($self->{handle}):-1 ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Inet.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Inet.pm new file mode 100644 index 000000000..68df0980f --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Inet.pm @@ -0,0 +1,142 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the tcp socket based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::Inet; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Spawning; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Spawning); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Internet (TCP) based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Socket; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel::Spawning->new(); + $self->{selectable} = !undef; + $self->{port} = $params{port}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + my $saddr = sockaddr_in( $self->{port}, INADDR_ANY ); + socket( *sfh, PF_INET, SOCK_STREAM, getprotobyname('tcp') ) or croak( "Can't open socket: $!" ); + setsockopt( *sfh, SOL_SOCKET, SO_REUSEADDR, 1 ); + bind( *sfh, $saddr ) or croak( "Can't bind: $!" ); + listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" ); + $self->{state} = 'open'; + $self->{handle} = *sfh; +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_handle = shift; + my $clone = $self->clone(); + $clone->{handle} = $new_handle; + $clone->{state} = 'connected'; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + local *cfh; + my $paddr = accept( *cfh, $self->{handle} ); + return( $self->_spawn( *cfh ) ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Serial.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Serial.pm new file mode 100644 index 000000000..7e4ad4730 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Serial.pm @@ -0,0 +1,160 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the serial port trigger channel +# class +# +package ZoneMinder::Trigger::Channel::Serial; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel; + +our @ISA = qw(ZoneMinder::Trigger::Channel); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Serial access trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use Device::SerialPort; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel->new; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + my $device = new Device::SerialPort( $self->{path} ); + $device->baudrate(9600); + $device->databits(8); + $device->parity('none'); + $device->stopbits(1); + $device->handshake('none'); + + $device->read_const_time(50); + $device->read_char_time(10); + + $self->{device} = $device; + $self->{state} = 'open'; + $self->{state} = 'connected'; +} + +sub close() +{ + my $self = shift; + $self->{device}->close(); + $self->{state} = 'closed'; +} + +sub read() +{ + my $self = shift; + my $buffer = $self->{device}->lookfor(); + if ( !$buffer || !length($buffer) ) + { + return( undef ); + } + Debug( "Read '$buffer' (".length($buffer)." bytes)\n" ); + return( $buffer ); +} + +sub write() +{ + my $self = shift; + my $buffer = shift; + my $nbytes = $self->{device}->write( $buffer ); + $self->{device}->write_drain(); + if ( !defined( $nbytes) || $nbytes < length($buffer) ) + { + Error( "Unable to write buffer '".$buffer.", expected ".length($buffer)." bytes, sent ".$nbytes.": $!\n" ); + return( undef ); + } + Debug( "Wrote '$buffer' ($nbytes bytes)\n" ); + return( !undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Spawning.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Spawning.pm new file mode 100644 index 000000000..ff726ac38 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Spawning.pm @@ -0,0 +1,112 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the handle based trigger channel +# classes that spawn new connections when connected. +# +package ZoneMinder::Trigger::Channel::Spawning; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Handle; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Handle); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base class for handle based triggers that spawn new connections +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +sub new +{ + my $class = shift; + my $port = shift; + my $self = ZoneMinder::Trigger::Channel::Handle->new(); + $self->{spawns} = !undef; + bless( $self, $class ); + return $self; +} + +sub spawns +{ + return( !undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Unix.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Unix.pm new file mode 100644 index 000000000..a671ccd66 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Channel/Unix.pm @@ -0,0 +1,141 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the unix socket based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::Unix; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Spawning; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Spawning); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Unix socket based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Socket; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel->new; + $self->{selectable} = !undef; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + unlink( $self->{path} ); + my $saddr = sockaddr_un( $self->{path} ); + socket( *sfh, PF_UNIX, SOCK_STREAM, 0 ) or croak( "Can't open socket: $!" ); + bind( *sfh, $saddr ) or croak( "Can't bind: $!" ); + listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" ); + $self->{handle} = *sfh; +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_handle = shift; + my $clone = $self->clone(); + $clone->{handle} = $new_handle; + $clone->{state} = 'connected'; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + local *cfh; + my $paddr = accept( *cfh, $self->{handle} ); + return( $self->_spawn( *cfh ) ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection.pm new file mode 100644 index 000000000..41b332d46 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection.pm @@ -0,0 +1,239 @@ +# ========================================================================== +# +# ZoneMinder Trigger Connection 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 base class definition of the trigger connection +# class tree +# +package ZoneMinder::Trigger::Connection; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = {}; + $self->{name} = $params{name}; + $self->{channel} = $params{channel}; + $self->{input} = $params{mode} =~ /r/i; + $self->{output} = $params{mode} =~ /w/i; + bless( $self, $class ); + return $self; +} + +sub clone +{ + my $self = shift; + my $clone = { %$self }; + bless $clone, ref $self; + return( $clone ); +} + +sub spawns +{ + my $self = shift; + return( $self->{channel}->spawns() ); +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_channel = shift; + my $clone = $self->clone(); + $clone->{channel} = $new_channel; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + my $new_channel = $self->{channel}->accept(); + return( $self->_spawn( $new_channel ) ); +} + +sub open() +{ + my $self = shift; + return( $self->{channel}->open() ); +} + +sub close() +{ + my $self = shift; + return( $self->{channel}->close() ); +} + +sub fileno() +{ + my $self = shift; + return( $self->{channel}->fileno() ); +} + +sub isOpen() +{ + my $self = shift; + return( $self->{channel}->isOpen() ); +} + +sub isConnected() +{ + my $self = shift; + return( $self->{channel}->isConnected() ); +} + +sub canRead() +{ + my $self = shift; + return( $self->{input} && $self->isConnected() ); +} + +sub canWrite() +{ + my $self = shift; + return( $self->{output} && $self->isConnected() ); +} + +sub getMessages +{ + my $self = shift; + my $buffer = $self->{channel}->read(); + + return( undef ) if ( !defined($buffer) ); + + my @messages = split( /\r?\n/, $buffer ); + return( \@messages ); +} + +sub putMessages +{ + my $self = shift; + my $messages = shift; + + if ( @$messages ) + { + my $buffer = join( "\n", @$messages ); + $buffer .= "\n"; + if ( !$self->{channel}->write( $buffer ) ) + { + Error( "Unable to write buffer '".$buffer." to connection ".$self->{name}." (".$self->fileno().")\n" ); + } + } + return( undef ); +} + +sub timedActions +{ +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + elsif ( defined($self->{channel}) ) + { + if ( exists($self->{channel}->{$name}) ) + { + return( $self->{channel}->{$name} ); + } + } + croak( "Can't access $name member of object of class $class" ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection/Example.pm b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection/Example.pm new file mode 100644 index 000000000..3bed2b351 --- /dev/null +++ b/scripts/ZoneMinder/blib/lib/ZoneMinder/Trigger/Connection/Example.pm @@ -0,0 +1,134 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 an example overriden trigger connection class +# +package ZoneMinder::Trigger::Connection::Example; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Connection; + +our @ISA = qw(ZoneMinder::Trigger::Connection); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Example overridden connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +sub new +{ + my $class = shift; + my $path = shift; + my $self = ZoneMinder::Trigger::Connection->new( @_ ); + bless( $self, $class ); + return $self; +} + +sub getMessages +{ + my $self = shift; + my $buffer = $self->{channel}->read(); + + return( undef ) if ( !defined($buffer) ); + + Debug( "Handling buffer '$buffer'\n" ); + my @messages = grep { s/-/|/g; 1; } split( /\r?\n/, $buffer ); + return( \@messages ); +} + +sub putMessages +{ + my $self = shift; + my $messages = shift; + + if ( @$messages ) + { + my $buffer = join( "\n", grep{ s/\|/-/; 1; } @$messages ); + $buffer .= "\n"; + if ( !$self->{channel}->write( $buffer ) ) + { + Error( "Unable to write buffer '".$buffer." to connection ".$self->{name}." (".$self->fileno().")\n" ); + } + } + return( undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/blib/lib/auto/ZoneMinder/.exists b/scripts/ZoneMinder/blib/lib/auto/ZoneMinder/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/man1/.exists b/scripts/ZoneMinder/blib/man1/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/man3/.exists b/scripts/ZoneMinder/blib/man3/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder.3pm new file mode 100644 index 000000000..166dbf786 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder.3pm @@ -0,0 +1,177 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder 3pm" +.TH ZoneMinder 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder \- Container module for common ZoneMinder modules +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use ZoneMinder; +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This module is a convenience container module that uses the +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database and ZoneMinder::Memory modules. It also +exports by default all symbols provided by the 'all' tag of +each of the modules. +.PP +Thus 'use'ing this module is equivalent to the following +.PP +.Vb 5 +\& use ZoneMinder::Base qw(:all); +\& use ZoneMinder::Config qw(:all); +\& use ZoneMinder::Logger qw(:all); +\& use ZoneMinder::Database qw(:all); +\& use ZoneMinder::Memory qw(:all); +.Ve +.PP +but is somewhat easier. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +All symbols exported by the 'all' tag of each of the included +modules. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database, ZoneMinder::Memory +.PP +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2005 by Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Base.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Base.3pm new file mode 100644 index 000000000..060aca327 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Base.3pm @@ -0,0 +1,157 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Base 3pm" +.TH ZoneMinder::Base 3pm "2012-09-11" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Base \- Base perl module for ZoneMinder +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use ZoneMinder::Base; +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +This module is the base module for the rest of the ZoneMinder modules. It is included by each of the other modules but serves no purpose other than to propagate the perl module version amongst the other modules. You will never need to use this module directly but if you write new ZoneMinder modules they should include it. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Config.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Config.3pm new file mode 100644 index 000000000..cafbc873f --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Config.3pm @@ -0,0 +1,166 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Config 3pm" +.TH ZoneMinder::Config 3pm "2012-09-11" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Config \- ZoneMinder configuration module. +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 1 +\& use ZoneMinder::Config qw(:all); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The ZoneMinder::Config module is used to import the ZoneMinder configuration from the database. It will do this at compile time in a \s-1BEGIN\s0 block and require access to the zm.conf file either in the current directory or in its defined location in order to determine database access details, configuration from this file will also be included. If the :all or :config tags are used then this configuration is exported into the namespace of the calling program or module. +.PP +Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. +.PP +.Vb 1 +\& $lang = ZM_LANG_DEFAULT; +.Ve +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +The :constants tag will export the \s-1ZM_PID\s0 constant which details the location of the zm.pid file +The :config tag will export all configuration from the database as well as any from the zm.conf file +The :all tag will export all above symbols. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigAdmin.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigAdmin.3pm new file mode 100644 index 000000000..9a29077ac --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigAdmin.3pm @@ -0,0 +1,180 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::ConfigAdmin 3pm" +.TH ZoneMinder::ConfigAdmin 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::ConfigAdmin \- ZoneMinder Configuration Administration module +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::ConfigAdmin; +\& use ZoneMinder::ConfigAdmin qw(:all); +\& +\& loadConfigFromDB(); +\& saveConfigToDB(); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The ZoneMinder:ConfigAdmin module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. +.PP +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. +.SH "METHODS" +.IX Header "METHODS" +.IP "loadConfigFromDB ();" 4 +.IX Item "loadConfigFromDB ();" +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. +.IP "saveConfigToDB ();" 4 +.IX Item "saveConfigToDB ();" +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. +.SH "POD ERRORS" +.IX Header "POD ERRORS" +Hey! \fBThe above document had some coding errors, which are explained below:\fR +.IP "Around line 188:" 4 +.IX Item "Around line 188:" +You forgot a '=back' before '=head2' diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigData.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigData.3pm new file mode 100644 index 000000000..38c7e4c2d --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::ConfigData.3pm @@ -0,0 +1,180 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::ConfigData 3pm" +.TH ZoneMinder::ConfigData 3pm "2012-09-11" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::ConfigData \- ZoneMinder Configuration Data module +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::ConfigData; +\& use ZoneMinder::ConfigData qw(:all); +\& +\& loadConfigFromDB(); +\& saveConfigToDB(); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The ZoneMinder:ConfigData module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. +.PP +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. +.SH "METHODS" +.IX Header "METHODS" +.IP "loadConfigFromDB ();" 4 +.IX Item "loadConfigFromDB ();" +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. +.IP "saveConfigToDB ();" 4 +.IX Item "saveConfigToDB ();" +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. +.SH "POD ERRORS" +.IX Header "POD ERRORS" +Hey! \fBThe above document had some coding errors, which are explained below:\fR +.IP "Around line 2031:" 4 +.IX Item "Around line 2031:" +You forgot a '=back' before '=head2' diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control.3pm new file mode 100644 index 000000000..d94097341 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control 3pm" +.TH ZoneMinder::Control 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::AxisV2.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::AxisV2.3pm new file mode 100644 index 000000000..a4d4e2970 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::AxisV2.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::AxisV2 3pm" +.TH ZoneMinder::Control::AxisV2 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Ncs370.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Ncs370.3pm new file mode 100644 index 000000000..9d7f662c8 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Ncs370.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::Ncs370 3pm" +.TH ZoneMinder::Control::Ncs370 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PanasonicIP.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PanasonicIP.3pm new file mode 100644 index 000000000..1e87ff0b2 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PanasonicIP.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::PanasonicIP 3pm" +.TH ZoneMinder::Control::PanasonicIP 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PelcoD.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PelcoD.3pm new file mode 100644 index 000000000..29378242f --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::PelcoD.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::PelcoD 3pm" +.TH ZoneMinder::Control::PelcoD 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Visca.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Visca.3pm new file mode 100644 index 000000000..3a1950937 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::Visca.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::Visca 3pm" +.TH ZoneMinder::Control::Visca 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::mjpgStreamer.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::mjpgStreamer.3pm new file mode 100644 index 000000000..87abf286e --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Control::mjpgStreamer.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Control::mjpgStreamer 3pm" +.TH ZoneMinder::Control::mjpgStreamer 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2005 by Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Database.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Database.3pm new file mode 100644 index 000000000..72c7b141a --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Database.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Database 3pm" +.TH ZoneMinder::Database 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::General.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::General.3pm new file mode 100644 index 000000000..8040b6b33 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::General.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::General 3pm" +.TH ZoneMinder::General 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Logger.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Logger.3pm new file mode 100644 index 000000000..48aec4433 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Logger.3pm @@ -0,0 +1,259 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Logger 3pm" +.TH ZoneMinder::Logger 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Logger \- ZoneMinder Logger module +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Logger; +\& use ZoneMinder::Logger qw(:all); +\& +\& logInit( "myproc", DEBUG ); +\& +\& Debug( "This is what is happening" ); +\& Info( "Something interesting is happening" ); +\& Warning( "Something might be going wrong." ); +\& Error( "Something has gone wrong!!" ); +\& Fatal( "Something has gone badly wrong, gotta stop!!" ); +\& Panic( "Something fundamental has gone wrong, die with stack trace ); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The ZoneMinder:Logger module contains the common debug and error reporting routines used by the ZoneMinder scripts. +.PP +To use debug in your scripts you need to include this module, and call logInit. Thereafter you can sprinkle Debug or Error calls etc throughout the code safe in the knowledge that they will be reported to your error log, and possibly the syslogger, in a meaningful and consistent format. +.PP +Debug is discussed in terms of levels where 1 and above (currently only 1 for scripts) is considered debug, 0 is considered as informational, \-1 is a warning, \-2 is an error and \-3 is a fatal error or panic. Where levels are mentioned below as thresholds the value given and anything with a lower level (ie. more serious) will be included. +.SH "METHODS" +.IX Header "METHODS" +.ie n .IP "logInit ( $id, %options );" 4 +.el .IP "logInit ( \f(CW$id\fR, \f(CW%options\fR );" 4 +.IX Item "logInit ( $id, %options );" +Initialises the debug and prepares the logging for forthcoming operations. If not called explicitly it will be called by the first debug call in your script, but with default (and probably meaningless) options. The only compulsory arguments are \f(CW$id\fR which must be a string that will identify debug coming from this script in mixed logs. Other options may be provided as below, +.Sp +.Vb 8 +\& Option Default Description +\& \-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\- +\& level INFO The initial debug level which defines which statements are output and which are ignored +\& trace 0 Whether to use the Carp::shortmess format in debug statements to identify where the debug was emitted from +\& termLevel NOLOG At what level debug is written to terminal standard error, 0 is no, 1 is yes, 2 is write only if terminal +\& databaseLevel INFO At what level debug is written to the Log table in the database; +\& fileLevel NOLOG At what level debug is written to a log file of the format of .log in the standard log directory. +\& syslogLevel INFO At what level debug is written to syslog. +.Ve +.Sp +To disable any of these action entirely set to \s-1NOLOG\s0 +.IP "logTerm ();" 4 +.IX Item "logTerm ();" +Used to end the debug session and close any logs etc. Not usually necessary. +.ie n .IP "$id = logId ( [$id] );" 4 +.el .IP "\f(CW$id\fR = logId ( [$id] );" 4 +.IX Item "$id = logId ( [$id] );" +.PD 0 +.ie n .IP "$level = logLevel ( [$level] );" 4 +.el .IP "\f(CW$level\fR = logLevel ( [$level] );" 4 +.IX Item "$level = logLevel ( [$level] );" +.ie n .IP "$trace = logTrace ( [$trace] );" 4 +.el .IP "\f(CW$trace\fR = logTrace ( [$trace] );" 4 +.IX Item "$trace = logTrace ( [$trace] );" +.ie n .IP "$level = logLevel ( [$level] );" 4 +.el .IP "\f(CW$level\fR = logLevel ( [$level] );" 4 +.IX Item "$level = logLevel ( [$level] );" +.ie n .IP "$termLevel = logTermLevel ( [$termLevel] );" 4 +.el .IP "\f(CW$termLevel\fR = logTermLevel ( [$termLevel] );" 4 +.IX Item "$termLevel = logTermLevel ( [$termLevel] );" +.ie n .IP "$databaseLevel = logDatabaseLevel ( [$databaseLevel] );" 4 +.el .IP "\f(CW$databaseLevel\fR = logDatabaseLevel ( [$databaseLevel] );" 4 +.IX Item "$databaseLevel = logDatabaseLevel ( [$databaseLevel] );" +.ie n .IP "$fileLevel = logFileLevel ( [$fileLevel] );" 4 +.el .IP "\f(CW$fileLevel\fR = logFileLevel ( [$fileLevel] );" 4 +.IX Item "$fileLevel = logFileLevel ( [$fileLevel] );" +.ie n .IP "$syslogLevel = logSyslogLevel ( [$syslogLevel] );" 4 +.el .IP "\f(CW$syslogLevel\fR = logSyslogLevel ( [$syslogLevel] );" 4 +.IX Item "$syslogLevel = logSyslogLevel ( [$syslogLevel] );" +.PD +These methods can be used to get and set the current settings as defined in logInit. +.ie n .IP "Debug( $string );" 4 +.el .IP "Debug( \f(CW$string\fR );" 4 +.IX Item "Debug( $string );" +This method will output a debug message if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1DBG\s0 string in the logs. +.ie n .IP "Info( $string );" 4 +.el .IP "Info( \f(CW$string\fR );" 4 +.IX Item "Info( $string );" +This method will output an informational message if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1INF\s0 string in the logs. +.ie n .IP "Warning( $string );" 4 +.el .IP "Warning( \f(CW$string\fR );" 4 +.IX Item "Warning( $string );" +This method will output a warning message if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1WAR\s0 string in the logs. +.ie n .IP "Error( $string );" 4 +.el .IP "Error( \f(CW$string\fR );" 4 +.IX Item "Error( $string );" +This method will output an error message if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1ERR\s0 string in the logs. +.ie n .IP "Fatal( $string );" 4 +.el .IP "Fatal( \f(CW$string\fR );" 4 +.IX Item "Fatal( $string );" +This method will output a fatal error message and then die if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1FAT\s0 string in the logs. +.ie n .IP "Panic( $string );" 4 +.el .IP "Panic( \f(CW$string\fR );" 4 +.IX Item "Panic( $string );" +This method will output a panic error message and then die with a stack trace if the current debug level permits it, otherwise does nothing. This message will be tagged with the \s-1PNC\s0 string in the logs. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +The :constants tag will export the debug constants which define the various levels of debug +The :variables tag will export variables containing the current debug id and level +The :functions tag will export the debug functions. This or :all is what you would normally use. +The :all tag will export all above symbols. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Carp +Sys::Syslog +.PP +The ZoneMinder \s-1README\s0 file Troubleshooting section for an extended discussion on the use and configuration of syslog with ZoneMinder. +.PP +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. +.SH "POD ERRORS" +.IX Header "POD ERRORS" +Hey! \fBThe above document had some coding errors, which are explained below:\fR +.IP "Around line 830:" 4 +.IX Item "Around line 830:" +You forgot a '=back' before '=head2' diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Memory.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Memory.3pm new file mode 100644 index 000000000..048b11fcd --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Memory.3pm @@ -0,0 +1,313 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Memory 3pm" +.TH ZoneMinder::Memory 3pm "2012-09-11" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::MappedMem \- ZoneMinder Mapped Memory access module +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::MappedMem; +\& use ZoneMinder::MappedMem qw(:all); +\& +\& if ( zmMemVerify( $monitor ) ) +\& { +\& $state = zmGetMonitorState( $monitor ); +\& if ( $state == STATE_ALARM ) +\& { +\& ... +\& } +\& } +\& +\& ( $lri, $lwi ) = zmMemRead( $monitor, [ "shared_data:last_read_index", "shared_data:last_write_index" ] ); +\& zmMemWrite( $monitor, { "trigger_data:trigger_showtext" => "Some Text" } ); +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The ZoneMinder:MappedMem module contains methods for accessing and writing to mapped memory as well as helper methods for common operations. +.PP +The core elements of ZoneMinder used mapped memory to allow multiple access to resources. Although ZoneMinder scripts have used this information before, up until now it was difficult to access and prone to errors. This module introduces a common \s-1API\s0 for mapped memory access (both reading and writing) making it a lot easier to customise scripts or even create your own. +.PP +All the methods listed below require a 'monitor' parameter. This must be a reference to a hash with at least the 'Id' field set to the monitor id of the mapped memory you wish to access. Using database methods to select the monitor details will also return this kind of data. Some of the mapped memory methods will add and amend new fields to this hash. +.SH "METHODS" +.IX Header "METHODS" +.ie n .IP "zmMemVerify ( $monitor );" 4 +.el .IP "zmMemVerify ( \f(CW$monitor\fR );" 4 +.IX Item "zmMemVerify ( $monitor );" +Verify that the mapped memory of the monitor given exists and is valid. It will return an undefined value if it is not valid. You should generally call this method first before using any of the other methods, but most of the remaining methods will also do so if the memory has not already been verified. +.ie n .IP "zmMemInvalidate ( $monitor );" 4 +.el .IP "zmMemInvalidate ( \f(CW$monitor\fR );" 4 +.IX Item "zmMemInvalidate ( $monitor );" +Following an error, reset the mapped memory ids and attempt to reverify on the next operation. This is mostly used when a mapped memory segment has gone away and been recreated with a different id. +.ie n .IP "zmMemRead ( $monitor, $readspec );" 4 +.el .IP "zmMemRead ( \f(CW$monitor\fR, \f(CW$readspec\fR );" 4 +.IX Item "zmMemRead ( $monitor, $readspec );" +This method is used to read data from mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'readspec' must either be a string of the form \*(L"
:\*(R" or a reference to an array of strings of the same format. In the first case a single value is returned, in the latter case a list of values is return. Errors will cause undefined to be returned. The allowable sections and field names are described below. +.ie n .IP "zmMemWrite ( $monitor, $writespec );" 4 +.el .IP "zmMemWrite ( \f(CW$monitor\fR, \f(CW$writespec\fR );" 4 +.IX Item "zmMemWrite ( $monitor, $writespec );" +This method is used to write data to mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'writespec' must be a reference to a hash with keys of the form \*(L"
:\*(R" and values as the data to be written. Errors will cause undefined to be returned, otherwise a non-undefined value will be returned. The allowable sections and field names are described below. +.ie n .IP "$state = zmGetMonitorState ( $monitor );" 4 +.el .IP "\f(CW$state\fR = zmGetMonitorState ( \f(CW$monitor\fR );" 4 +.IX Item "$state = zmGetMonitorState ( $monitor );" +Return the current state of the given monitor. This is an integer value and can be compared with the \s-1STATE\s0 constants given below. +.ie n .IP "$event_id = zmGetLastEvent ( $monitor );" 4 +.el .IP "\f(CW$event_id\fR = zmGetLastEvent ( \f(CW$monitor\fR );" 4 +.IX Item "$event_id = zmGetLastEvent ( $monitor );" +Return the event id of the last event that the monitor generated, or 0 if no event has been generated by the current monitor process. +.ie n .IP "zmIsAlarmed ( $monitor );" 4 +.el .IP "zmIsAlarmed ( \f(CW$monitor\fR );" 4 +.IX Item "zmIsAlarmed ( $monitor );" +Return 1 if the monitor given is currently in an alarm state, 0 otherwise. +.ie n .IP "zmInAlarm ( $monitor );" 4 +.el .IP "zmInAlarm ( \f(CW$monitor\fR );" 4 +.IX Item "zmInAlarm ( $monitor );" +Return 1 if the monitor given is currently in an alarm or alerted state, 0 otherwise. +.ie n .IP "zmHasAlarmed ( $monitor );" 4 +.el .IP "zmHasAlarmed ( \f(CW$monitor\fR );" 4 +.IX Item "zmHasAlarmed ( $monitor );" +Return 1 if the given monitor is in an alarm state, or has been in an alarm state since the last call to this method. +.ie n .IP "( $x, $y ) = zmGetAlarmLocation ( $monitor );" 4 +.el .IP "( \f(CW$x\fR, \f(CW$y\fR ) = zmGetAlarmLocation ( \f(CW$monitor\fR );" 4 +.IX Item "( $x, $y ) = zmGetAlarmLocation ( $monitor );" +Return an x,y pair indicating the image co-ordinates of the centre of the last motion event generated by the given monitor. If no event has been generated by the current monitor process, or the alarm was not motion related, returns \-1,\-1. +.ie n .IP "zmGetLastWriteTime ( $monitor );" 4 +.el .IP "zmGetLastWriteTime ( \f(CW$monitor\fR );" 4 +.IX Item "zmGetLastWriteTime ( $monitor );" +Returns the time (in utc seconds) since the last image was captured by the given monitor and written to shared memory, or 0 otherwise. +.ie n .IP "zmGetLastReadTime ( $monitor );" 4 +.el .IP "zmGetLastReadTime ( \f(CW$monitor\fR );" 4 +.IX Item "zmGetLastReadTime ( $monitor );" +Returns the time (in utc seconds) since the last image was read from shared memory by the analysis daemon of the given monitor, or 0 otherwise or if the monitor is in monitor only mode. +.ie n .IP "zmMonitorSuspend ( $monitor );" 4 +.el .IP "zmMonitorSuspend ( \f(CW$monitor\fR );" 4 +.IX Item "zmMonitorSuspend ( $monitor );" +Suspend the given monitor from generating events caused by motion. This method can be used to prevent camera actions such as panning or zooming from causing events. If configured to do so, the monitor may automatically resume after a defined period. +.ie n .IP "zmMonitorResume ( $monitor );" 4 +.el .IP "zmMonitorResume ( \f(CW$monitor\fR );" 4 +.IX Item "zmMonitorResume ( $monitor );" +Allow the given monitor to resume generating events caused by motion. +.ie n .IP "zmTriggerEventOn ( $monitor, $score, $cause [, $text, $showtext ] );" 4 +.el .IP "zmTriggerEventOn ( \f(CW$monitor\fR, \f(CW$score\fR, \f(CW$cause\fR [, \f(CW$text\fR, \f(CW$showtext\fR ] );" 4 +.IX Item "zmTriggerEventOn ( $monitor, $score, $cause [, $text, $showtext ] );" +Trigger the given monitor to generate an event. You must supply an event score and a cause string indicating the reason for the event. You may also supply a text string containing further details about the event and a showtext string which may be included in the timestamp annotation on any images captured during the event, if configured to do so. +.ie n .IP "zmTriggerEventOff ( $monitor );" 4 +.el .IP "zmTriggerEventOff ( \f(CW$monitor\fR );" 4 +.IX Item "zmTriggerEventOff ( $monitor );" +Trigger the given monitor to not generate any events. This method does not cancel zmTriggerEventOn, but is exclusive to it. This method is intended to allow external triggers to prevent normal events being generated by monitors in the same way as zmMonitorSuspend but applies to all events and not just motion, and is intended for longer timescales than are appropriate for suspension. +.ie n .IP "zmTriggerEventCancel ( $monitor );" 4 +.el .IP "zmTriggerEventCancel ( \f(CW$monitor\fR );" 4 +.IX Item "zmTriggerEventCancel ( $monitor );" +Cancel any previous trigger on or off requests. This stops a triggered alarm if it exists from a previous 'on' and allows events to be generated once more following a previous 'off'. +.ie n .IP "zmTriggerShowtext ( $monitor, $showtest );" 4 +.el .IP "zmTriggerShowtext ( \f(CW$monitor\fR, \f(CW$showtest\fR );" 4 +.IX Item "zmTriggerShowtext ( $monitor, $showtest );" +Indicate that the given text should be displayed in the timestamp annotation on any images captured, if the format of the annotation string defined for the monitor permits. +.SH "DATA" +.IX Header "DATA" +The data fields in mapped memory that may be accessed are as follows. There are two main sections, shared_data which is general data and trigger_data which is used for event triggering. Whilst reading from these fields is harmless, extreme care must be taken when writing to mapped memory, especially in the shared_data section as this is normally written to only by monitor capture and analysis processes. +.PP +.Vb 10 +\& shared_data The general mapped memory section +\& size The size, in bytes, of this section +\& valid Flag indicating whether this section has been initialised +\& active Flag indicating whether this monitor is active (enabled/disabled) +\& signal Flag indicating whether this monitor is reciving a valid signal +\& state The current monitor state, see the STATE constants below +\& last_write_index The last index, in the image buffer, that an image has been saved to +\& last_read_index The last index, in the image buffer, that an image has been analysed from +\& last_write_time The time (in utc seconds) when the last image was captured +\& last_read_time The time (in utc seconds) when the last image was analysed +\& last_event The id of the last event generated by the monitor analysis process, 0 if none +\& action The monitor actions bitmask, see the ACTION constants below +\& brightness Read/write location for the current monitor brightness +\& hue Read/write location for the current monitor hue +\& colour Read/write location for the current monitor colour +\& contrast Read/write location for the current monitor contrast +\& alarm_x Image x co\-ordinate (from left) of the centre of the last motion event, \-1 if none +\& alarm_y Image y co\-ordinate (from top) of the centre of the last motion event, \-1 if none +\& +\& trigger_data The triggered event mapped memory section +\& size The size, in bytes of this section +\& trigger_state The current trigger state, see the TRIGGER constants below +\& trigger_score The current triggered event score +\& trigger_cause The current triggered event cause string +\& trigger_text The current triggered event descriptive text string +\& trigger_showtext The triggered text that will be displayed on captured image timestamps +.Ve +.SH "CONSTANTS" +.IX Header "CONSTANTS" +The following constants are used by the methods above, but can also be used by user scripts if required. +.IP "\s-1STATE_IDLE\s0 \s-1STATE_PREALARM\s0 \s-1STATE_ALARM\s0 \s-1STATE_ALERT\s0 \s-1STATE_TAPE\s0" 4 +.IX Item "STATE_IDLE STATE_PREALARM STATE_ALARM STATE_ALERT STATE_TAPE" +These constants define the state of the monitor with respect to alarms and events. They are used in the shared_data:state field. +.IP "\s-1ACTION_GET\s0 \s-1ACTION_SET\s0 \s-1ACTION_RELOAD\s0 \s-1ACTION_SUSPEND\s0 \s-1ACTION_RESUME\s0" 4 +.IX Item "ACTION_GET ACTION_SET ACTION_RELOAD ACTION_SUSPEND ACTION_RESUME" +These constants defines the various values that can exist in the shared_data:action field. This is a bitmask which when non-zero defines an action that an executing monitor process should take. \s-1ACTION_GET\s0 requires that the current values of brightness, contrast, colour and hue are taken from the camera and written to the equivalent mapped memory fields. \s-1ACTION_SET\s0 implies the reverse, that the values in mapped memory should be written to the camera. \s-1ACTION_RELOAD\s0 signal that the monitor process should reload itself from the database in case any settings have changed there. \s-1ACTION_SUSPEND\s0 signals that a monitor should stop exaiming images for motion, though other alarms may still occur. \s-1ACTION_RESUME\s0 sigansl that a monitor should resume motion detectiom. +.IP "\s-1TRIGGER_CANCEL\s0 \s-1TRIGGER_ON\s0 \s-1TRIGGER_OFF\s0" 4 +.IX Item "TRIGGER_CANCEL TRIGGER_ON TRIGGER_OFF" +These constants are used in the definition of external triggers. \s-1TRIGGER_CANCEL\s0 is used to indicated that any previous trigger settings should be cancelled, \s-1TRIGGER_ON\s0 signals that an alarm should be created (or continued)) as a result of the current trigger and \s-1TRIGGER_OFF\s0 signals that the trigger should prevent any alarms from being generated. See the trigger methods above for further details. +.SH "EXPORT" +.IX Header "EXPORT" +None by default. +The :constants tag will export the mapped memory constants which mostly define enumerations for the variables held in memory +The :functions tag will export the mapped memory access functions. +The :all tag will export all above symbols. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +http://www.zoneminder.com +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. +.SH "POD ERRORS" +.IX Header "POD ERRORS" +Hey! \fBThe above document had some coding errors, which are explained below:\fR +.IP "Around line 727:" 4 +.IX Item "Around line 727:" +You forgot a '=back' before '=head1' +.IP "Around line 729:" 4 +.IX Item "Around line 729:" +\&'=item' outside of any '=over' +.IP "Around line 801:" 4 +.IX Item "Around line 801:" +You forgot a '=back' before '=head1' +.IP "Around line 836:" 4 +.IX Item "Around line 836:" +\&'=item' outside of any '=over' +.IP "Around line 848:" 4 +.IX Item "Around line 848:" +You forgot a '=back' before '=head1' diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel.3pm new file mode 100644 index 000000000..02f6655b1 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel 3pm" +.TH ZoneMinder::Trigger::Channel 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::File.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::File.3pm new file mode 100644 index 000000000..21489277f --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::File.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::File 3pm" +.TH ZoneMinder::Trigger::Channel::File 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Handle.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Handle.3pm new file mode 100644 index 000000000..b951b38cc --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Handle.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::Handle 3pm" +.TH ZoneMinder::Trigger::Channel::Handle 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Inet.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Inet.3pm new file mode 100644 index 000000000..8b0507d3a --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Inet.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::Inet 3pm" +.TH ZoneMinder::Trigger::Channel::Inet 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Serial.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Serial.3pm new file mode 100644 index 000000000..cdbfb2c1f --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Serial.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::Serial 3pm" +.TH ZoneMinder::Trigger::Channel::Serial 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Spawning.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Spawning.3pm new file mode 100644 index 000000000..413e5262b --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Spawning.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::Spawning 3pm" +.TH ZoneMinder::Trigger::Channel::Spawning 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Unix.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Unix.3pm new file mode 100644 index 000000000..de4bb999a --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Channel::Unix.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Channel::Unix 3pm" +.TH ZoneMinder::Trigger::Channel::Unix 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection.3pm new file mode 100644 index 000000000..019306786 --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Connection 3pm" +.TH ZoneMinder::Trigger::Connection 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection::Example.3pm b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection::Example.3pm new file mode 100644 index 000000000..49aaf4a4d --- /dev/null +++ b/scripts/ZoneMinder/blib/man3/ZoneMinder::Trigger::Connection::Example.3pm @@ -0,0 +1,169 @@ +.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "ZoneMinder::Trigger::Connection::Example 3pm" +.TH ZoneMinder::Trigger::Connection::Example 3pm "2012-07-17" "perl v5.14.2" "User Contributed Perl Documentation" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +ZoneMinder::Database \- Perl extension for blah blah blah +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +.Vb 2 +\& use ZoneMinder::Database; +\& blah blah blah +.Ve +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Stub documentation for ZoneMinder, created by h2xs. It looks like the +author of the extension was negligent enough to leave the stub +unedited. +.PP +Blah blah blah. +.SS "\s-1EXPORT\s0" +.IX Subsection "EXPORT" +None by default. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +Mention other useful documentation such as the documentation of +related modules or operating system documentation (such as man pages +in \s-1UNIX\s0), or any relevant external documentation such as RFCs or +standards. +.PP +If you have a mailing list set up for your module, mention it here. +.PP +If you have a web site set up for your module, mention it here. +.SH "AUTHOR" +.IX Header "AUTHOR" +Philip Coombes, +.SH "COPYRIGHT AND LICENSE" +.IX Header "COPYRIGHT AND LICENSE" +Copyright (C) 2001\-2008 Philip Coombes +.PP +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. diff --git a/scripts/ZoneMinder/blib/script/.exists b/scripts/ZoneMinder/blib/script/.exists new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/lib/ZoneMinder.pm b/scripts/ZoneMinder/lib/ZoneMinder.pm new file mode 100644 index 000000000..41c972650 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder.pm @@ -0,0 +1,130 @@ +# ========================================================================== +# +# ZoneMinder Common 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; + +use 5.006; +use strict; +use warnings; + +require Exporter; +use ZoneMinder::Base qw(:all); +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); +use ZoneMinder::General qw(:all); +use ZoneMinder::Database qw(:all); +use ZoneMinder::Memory qw(:all); + +our @ISA = qw(Exporter ZoneMinder::Base ZoneMinder::Config ZoneMinder::Logger ZoneMinder::General ZoneMinder::Database ZoneMinder::Memory); + +# 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 = ( + 'base' => [ + @ZoneMinder::Base::EXPORT_OK + ], + 'config' => [ + @ZoneMinder::Config::EXPORT_OK + ], + 'debug' => [ + @ZoneMinder::Logger::EXPORT_OK + ], + 'general' => [ + @ZoneMinder::General::EXPORT_OK + ], + 'database' => [ + @ZoneMinder::Database::EXPORT_OK + ], + 'memory' => [ + @ZoneMinder::Memory::EXPORT_OK + ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = @{ $EXPORT_TAGS{'all'} }; + +our @EXPORT = ( @EXPORT_OK ); + +our $VERSION = $ZoneMinder::Base::VERSION; + +1; +__END__ + +=head1 NAME + +ZoneMinder - Container module for common ZoneMinder modules + +=head1 SYNOPSIS + + use ZoneMinder; + +=head1 DESCRIPTION + +This module is a convenience container module that uses the +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database and ZoneMinder::Memory modules. It also +exports by default all symbols provided by the 'all' tag of +each of the modules. + +Thus 'use'ing this module is equivalent to the following + + use ZoneMinder::Base qw(:all); + use ZoneMinder::Config qw(:all); + use ZoneMinder::Logger qw(:all); + use ZoneMinder::Database qw(:all); + use ZoneMinder::Memory qw(:all); + +but is somewhat easier. + +=head2 EXPORT + +All symbols exported by the 'all' tag of each of the included +modules. + +=head1 SEE ALSO + +ZoneMinder::Base, ZoneMinder::Common, ZoneMinder::Logger, +ZoneMinder::Database, ZoneMinder::Memory + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005 by 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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Base.pm b/scripts/ZoneMinder/lib/ZoneMinder/Base.pm new file mode 100644 index 000000000..095ddc37b --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Base.pm @@ -0,0 +1,86 @@ +# ========================================================================== +# +# ZoneMinder Base 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::Base; + +use 5.006; +use strict; +use warnings; + +require Exporter; + +our @ISA = qw(Exporter); + +# 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 = ( 'all' => [ qw() ] ); + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = "1.25.0"; + +1; +__END__ + +=head1 NAME + +ZoneMinder::Base - Base perl module for ZoneMinder + +=head1 SYNOPSIS + + use ZoneMinder::Base; + +=head1 DESCRIPTION + +This module is the base module for the rest of the ZoneMinder modules. It is included by each of the other modules but serves no purpose other than to propagate the perl module version amongst the other modules. You will never need to use this module directly but if you write new ZoneMinder modules they should include it. + +=head2 EXPORT + +None by default. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in new file mode 100644 index 000000000..37119f725 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Base.pm.in @@ -0,0 +1,86 @@ +# ========================================================================== +# +# ZoneMinder Base 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::Base; + +use 5.006; +use strict; +use warnings; + +require Exporter; + +our @ISA = qw(Exporter); + +# 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 = ( 'all' => [ qw() ] ); + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = "@VERSION@"; + +1; +__END__ + +=head1 NAME + +ZoneMinder::Base - Base perl module for ZoneMinder + +=head1 SYNOPSIS + + use ZoneMinder::Base; + +=head1 DESCRIPTION + +This module is the base module for the rest of the ZoneMinder modules. It is included by each of the other modules but serves no purpose other than to propagate the perl module version amongst the other modules. You will never need to use this module directly but if you write new ZoneMinder modules they should include it. + +=head2 EXPORT + +None by default. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm new file mode 100644 index 000000000..e447f86f9 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm @@ -0,0 +1,145 @@ +# ========================================================================== +# +# ZoneMinder Config 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::Config; + +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_CONFIG; # Get populated by BEGIN + +our %EXPORT_TAGS = ( + 'constants' => [ qw( + ZM_PID + ) ] +); +push( @{$EXPORT_TAGS{config}}, @EXPORT_CONFIG ); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +use constant ZM_PID => "/var/run/zm/zm.pid"; # Path to the ZoneMinder run pid file +use constant ZM_CONFIG => "/etc/zm/zm.conf"; # Path to the ZoneMinder config file + +use Carp; + +# Load the config from the database into the symbol table +BEGIN +{ + no strict 'refs'; + + my $config_file = ZM_CONFIG; + ( my $local_config_file = $config_file ) =~ s|^.*/|./|; + if ( -s $local_config_file && -r $local_config_file ) + { + print( STDERR "Warning, overriding installed $local_config_file file with local copy\n" ); + $config_file = $local_config_file; + } + open( CONFIG, "<".$config_file ) or croak( "Can't open config file '$config_file': $!" ); + foreach my $str ( ) + { + next if ( $str =~ /^\s*$/ ); + next if ( $str =~ /^\s*#/ ); + my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.+?)\s*$/; + $name =~ tr/a-z/A-Z/; + *{$name} = sub { $value }; + push( @EXPORT_CONFIG, $name ); + } + close( CONFIG ); + + use DBI; + my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_HOST, &ZM_DB_USER, &ZM_DB_PASS ); + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + while( my $config = $sth->fetchrow_hashref() ) + { + *{$config->{Name}} = sub { $config->{Value} }; + push( @EXPORT_CONFIG, $config->{Name} ); + } + $sth->finish(); + $dbh->disconnect(); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::Config - ZoneMinder configuration module. + +=head1 SYNOPSIS + + use ZoneMinder::Config qw(:all); + +=head1 DESCRIPTION + +The ZoneMinder::Config module is used to import the ZoneMinder configuration from the database. It will do this at compile time in a BEGIN block and require access to the zm.conf file either in the current directory or in its defined location in order to determine database access details, configuration from this file will also be included. If the :all or :config tags are used then this configuration is exported into the namespace of the calling program or module. + +Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. + + $lang = ZM_LANG_DEFAULT; + +=head2 EXPORT + +None by default. +The :constants tag will export the ZM_PID constant which details the location of the zm.pid file +The :config tag will export all configuration from the database as well as any from the zm.conf file +The :all tag will export all above symbols. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in new file mode 100644 index 000000000..fbd9ea374 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Config.pm.in @@ -0,0 +1,145 @@ +# ========================================================================== +# +# ZoneMinder Config 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::Config; + +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_CONFIG; # Get populated by BEGIN + +our %EXPORT_TAGS = ( + 'constants' => [ qw( + ZM_PID + ) ] +); +push( @{$EXPORT_TAGS{config}}, @EXPORT_CONFIG ); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +use constant ZM_PID => "@ZM_PID@"; # Path to the ZoneMinder run pid file +use constant ZM_CONFIG => "@ZM_CONFIG@"; # Path to the ZoneMinder config file + +use Carp; + +# Load the config from the database into the symbol table +BEGIN +{ + no strict 'refs'; + + my $config_file = ZM_CONFIG; + ( my $local_config_file = $config_file ) =~ s|^.*/|./|; + if ( -s $local_config_file && -r $local_config_file ) + { + print( STDERR "Warning, overriding installed $local_config_file file with local copy\n" ); + $config_file = $local_config_file; + } + open( CONFIG, "<".$config_file ) or croak( "Can't open config file '$config_file': $!" ); + foreach my $str ( ) + { + next if ( $str =~ /^\s*$/ ); + next if ( $str =~ /^\s*#/ ); + my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*(.+?)\s*$/; + $name =~ tr/a-z/A-Z/; + *{$name} = sub { $value }; + push( @EXPORT_CONFIG, $name ); + } + close( CONFIG ); + + use DBI; + my $dbh = DBI->connect( "DBI:mysql:database=".&ZM_DB_NAME.";host=".&ZM_DB_HOST, &ZM_DB_USER, &ZM_DB_PASS ); + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + while( my $config = $sth->fetchrow_hashref() ) + { + *{$config->{Name}} = sub { $config->{Value} }; + push( @EXPORT_CONFIG, $config->{Name} ); + } + $sth->finish(); + $dbh->disconnect(); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::Config - ZoneMinder configuration module. + +=head1 SYNOPSIS + + use ZoneMinder::Config qw(:all); + +=head1 DESCRIPTION + +The ZoneMinder::Config module is used to import the ZoneMinder configuration from the database. It will do this at compile time in a BEGIN block and require access to the zm.conf file either in the current directory or in its defined location in order to determine database access details, configuration from this file will also be included. If the :all or :config tags are used then this configuration is exported into the namespace of the calling program or module. + +Once the configuration has been imported then configuration variables are defined as constants and can be accessed directory by name, e.g. + + $lang = ZM_LANG_DEFAULT; + +=head2 EXPORT + +None by default. +The :constants tag will export the ZM_PID constant which details the location of the zm.pid file +The :config tag will export all configuration from the database as well as any from the zm.conf file +The :all tag will export all above symbols. + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm b/scripts/ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm new file mode 100644 index 000000000..8ee1ec82b --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigAdmin.pm @@ -0,0 +1,213 @@ +# ========================================================================== +# +# ZoneMinder Config Admin 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigAdmin; + +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( + loadConfigFromDB + saveConfigToDB + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'functions'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Administration +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::ConfigData qw(:all); + +use Carp; + +sub loadConfigFromDB +{ + print( "Loading config from DB\n" ); + my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + + if ( !$dbh ) + { + print( "Error: unable to load options from database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "select * from Config"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute: ".$sth->errstr() ); + my $option_count = 0; + while( my $config = $sth->fetchrow_hashref() ) + { + my ( $name, $value ) = ( $config->{Name}, $config->{Value} ); + #print( "Name = '$name'\n" ); + my $option = $options_hash{$name}; + if ( !$option ) + { + warn( "No option '$name' found, removing" ); + next; + } + #next if ( $option->{category} eq 'hidden' ); + if ( defined($value) ) + { + if ( $option->{type} == $types{boolean} ) + { + $option->{value} = $value?"yes":"no"; + } + else + { + $option->{value} = $value; + } + } + $option_count++;; + } + $sth->finish(); + $dbh->disconnect(); + return( $option_count ); +} + +sub saveConfigToDB +{ + print( "Saving config to DB\n" ); + my $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + + if ( !$dbh ) + { + print( "Error: unable to save options to database: $DBI::errstr\n" ); + return( 0 ); + } + my $sql = "delete from Config"; + my $res = $dbh->do( $sql ) or croak( "Can't do '$sql': ".$dbh->errstr() ); + + $sql = "replace into Config set Id = ?, Name = ?, Value = ?, Type = ?, DefaultValue = ?, Hint = ?, Pattern = ?, Format = ?, Prompt = ?, Help = ?, Category = ?, Readonly = ?, Requires = ?"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $option ( @options ) + { + #next if ( $option->{category} eq 'hidden' ); + #print( $option->{name}."\n" ) if ( !$option->{category} ); + $option->{db_type} = $option->{type}->{db_type}; + $option->{db_hint} = $option->{type}->{hint}; + $option->{db_pattern} = $option->{type}->{pattern}; + $option->{db_format} = $option->{type}->{format}; + if ( $option->{db_type} eq "boolean" ) + { + $option->{db_value} = ($option->{value} eq "yes")?"1":"0"; + } + else + { + $option->{db_value} = $option->{value}; + } + if ( my $requires = $option->{requires} ) + { + $option->{db_requires} = join( ";", map { my $value = $_->{value}; $value = ($value eq "yes")?1:0 if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ); ( "$_->{name}=$value" ) } @$requires ); + } + else + { + } + my $res = $sth->execute( $option->{id}, $option->{name}, $option->{db_value}, $option->{db_type}, $option->{default}, $option->{db_hint}, $option->{db_pattern}, $option->{db_format}, $option->{description}, $option->{help}, $option->{category}, $option->{readonly}?1:0, $option->{db_requires} ) or croak( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + $dbh->disconnect(); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigAdmin - ZoneMinder Configuration Administration module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigAdmin; + use ZoneMinder::ConfigAdmin qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigAdmin module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm new file mode 100644 index 000000000..e108d8687 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm @@ -0,0 +1,2056 @@ +# ========================================================================== +# +# ZoneMinder Config Data Module, $Date: 2011-01-20 18:49:42 +0000 (Thu, 20 Jan 2011) $, $Revision: 3230 $ +# 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigData; + +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 = ( + 'data' => [ qw( + %types + @options + %options_hash + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'data'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Data +# +# ========================================================================== + +use Carp; + +our $configInitialised = 0; + +sub INIT +{ + initialiseConfig(); +} + +# Types +our %types = +( + string => { db_type=>"string", hint=>"string", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + alphanum => { db_type=>"string", hint=>"alphanumeric", pattern=>qr|^([a-zA-Z0-9-_]+)$|, format=>q( $1 ) }, + text => { db_type=>"text", hint=>"free text", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + boolean => { db_type=>"boolean", hint=>"yes|no", pattern=>qr|^([yn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : "no" ) }, + integer => { db_type=>"integer", hint=>"integer", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + decimal => { db_type=>"decimal", hint=>"decimal", pattern=>qr|^(\d+(?:\.\d+)?)$|, format=>q( $1 ) }, + hexadecimal => { db_type=>"hexadecimal", hint=>"hexadecimal", pattern=>qr|^(?:0x)?([0-9a-f]{1,8})$|, format=>q( "0x".$1 ) }, + tristate => { db_type=>"string", hint=>"auto|yes|no", pattern=>qr|^([ayn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : ($1 =~ /^n/ ? "no" : "auto" ) ) }, + abs_path => { db_type=>"string", hint=>"/absolute/path/to/somewhere", pattern=>qr|^((?:/[^/]*)+?)/?$|, format=>q( $1 ) }, + rel_path => { db_type=>"string", hint=>"relative/path/to/somewhere", pattern=>qr|^((?:[^/].*)?)/?$|, format=>q( $1 ) }, + directory => { db_type=>"string", hint=>"directory", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + file => { db_type=>"string", hint=>"filename", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + hostname => { db_type=>"string", hint=>"host.your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)$|, format=>q( $1 ) }, + url => { db_type=>"string", hint=>"http://host.your.domain/", pattern=>qr|^(?:http://)?(.+)$|, format=>q( "http://".$1 ) }, + email => { db_type=>"string", hint=>"your.name\@your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$|, format=>q( $1\@$2 ) }, +); + +our @options = +( + { + name => "ZM_LANG_DEFAULT", + default => "en_gb", + description => "Default language used by web interface", + help => "ZoneMinder allows the web interface to use languages other than English if the appropriate language file has been created and is present. This option allows you to change the default language that is used from the shipped language, British English, to another language", + type => $types{string}, + category => "system", + }, + { + name => "ZM_OPT_USE_AUTH", + default => "no", + description => "Authenticate user logins to ZoneMinder", + help => "ZoneMinder can run in two modes. The simplest is an entirely unauthenticated mode where anyone can access ZoneMinder and perform all tasks. This is most suitable for installations where the web server access is limited in other ways. The other mode enables user accounts with varying sets of permissions. Users must login or authenticate to access ZoneMinder and are limited by their defined permissions.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_TYPE", + default => "builtin", + description => "What is used to authenticate ZoneMinder users", + help => "ZoneMinder can use two methods to authenticate users when running in authenticated mode. The first is a builtin method where ZoneMinder provides facilities for users to log in and maintains track of their identity. The second method allows interworking with other methods such as http basic authentication which passes an independently authentication 'remote' user via http. In this case ZoneMinder would use the supplied user without additional authentication provided such a user is configured ion ZoneMinder.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"builtin|remote", pattern=>qr|^([br])|i, format=>q( $1 =~ /^b/ ? "builtin" : "remote" ) }, + category => "system", + }, + { + name => "ZM_AUTH_RELAY", + default => "hashed", + description => "Method used to relay authentication information", + help => "When ZoneMinder is running in authenticated mode it can pass user details between the web pages and the back end processes. There are two methods for doing this. This first is to use a time limited hashed string which contains no direct username or password details, the second method is to pass the username and passwords around in plaintext. This method is not recommend except where you do not have the md5 libraries available on your system or you have a completely isolated system with no external access. You can also switch off authentication relaying if your system is isolated in other ways.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"hashed|plain|none", pattern=>qr|^([hpn])|i, format=>q( ($1 =~ /^h/) ? "hashed" : ($1 =~ /^p/ ? "plain" : "none" ) ) }, + category => "system", + }, + { + name => "ZM_AUTH_HASH_SECRET", + default => "...Change me to something unique...", + description => "Secret for encoding hashed authentication information", + help => "When ZoneMinder is running in hashed authenticated mode it is necessary to generate hashed strings containing encrypted sensitive information such as usernames and password. Although these string are reasonably secure the addition of a random secret increases security substantially.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{string}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_IPS", + default => "yes", + description => "Include IP addresses in the authentication hash", + help => "When ZoneMinder is running in hashed authenticated mode it can optionally include the requesting IP address in the resultant hash. This adds an extra level of security as only requests from that address may use that authentication key. However in some circumstances, such as access over mobile networks, the requesting address can change for each request which will cause most requests to fail. This option allows you to control whether IP addresses are included in the authentication hash on your system. If you experience intermitent problems with authentication, switching this option off may help.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_LOGINS", + default => "no", + description => "Allow login by authentication hash", + help => "The normal process for logging into ZoneMinder is via the login screen with username and password. In some circumstances it may be desirable to allow access directly to one or more pages, for instance from a third party application. If this option is enabled then adding an 'auth' parameter to any request will include a shortcut login bypassing the login screen, if not already logged in. As authentication hashes are time and, optionally, IP limited this can allow short-term access to ZoneMinder screens from other web pages etc. In order to use this the calling application will hae to generate the authentication hash itself and ensure it is valid. If you use this option you should ensure that you have modified the ZM_AUTH_HASH_SECRET to somethign unique to your system.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_DIR_EVENTS", + default => "events", + description => "Directory where events are stored", + help => "This is the path to the events directory where all the event images and other miscellaneous files are stored. It is normally given as a subdirectory of the web directory you have specified earlier however if disk space is tight it can reside on another partition in which case you should create a link from that area to the path you give here.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_USE_DEEP_STORAGE", + default => "yes", + description => "Use a deep filesystem hierarchy for events", + help => "Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date.", + type => $types{boolean}, + category => "paths", + }, + { + name => "ZM_DIR_IMAGES", + default => "images", + description => "Directory where the images that the ZoneMinder client generates are stored", + help => "ZoneMinder generates a myriad of images, mosty of which are associated with events. For those that aren't this is where they go.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_DIR_SOUNDS", + default => "sounds", + description => "Directory to the sounds that the ZoneMinder client can use", + help => "ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where (relative to the web root) to look for this file.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_PATH_ZMS", + default => "/cgi-bin/nph-zms", + description => "Web path to zms streaming server", + help => "The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing 'zms' to 'nph-zms'.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_COLOUR_JPEG_FILES", + default => "yes", + description => "Colourise greyscale JPEG files", + help => "Cameras that capture in greyscale can write their captured images to jpeg files with a corresponding greyscale colour space. This saves a small amount of disk space over colour ones. However some tools such as ffmpeg either fail to work with this colour space or have to convert it beforehand. Setting this option to yes uses up a little more space but makes creation of MPEG files much faster.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_ADD_JPEG_COMMENTS", + default => "no", + description => "Add jpeg timestamp annotations as file header comments", + help => "JPEG files may have a number of extra fields added to the file header. The comment field may have any kind of text added. This options allows you to have the same text that is used to annotate the image additionally included as a file header comment. If you archive event images to other locations this may help you locate images for particular events or times if you use software that can read comment headers.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_JPEG_FILE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the saved event files (1-100)", + help => "When ZoneMinder detects an event it will save the images associated with that event to files. These files are in the JPEG format and can be viewed or streamed later. This option specifies what image quality should be used to save these files. A higher number means better quality but less compression so will take up more disk space and take longer to view over a slow connection. By contrast a low number means smaller, quicker to view, files but at the price of lower quality images. This setting applies to all images written except if the capture image has caused an alarm and the alarm file quality option is set at a higher value when that is used instead.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_JPEG_ALARM_FILE_QUALITY", + default => "0", + description => "Set the JPEG quality setting for the saved event files during an alarm (1-100)", + help => "This value is equivalent to the regular jpeg file quality setting above except that it only applies to images saved while in an alarm state and then only if this value is set to a higher quality setting than the ordinary file setting. If set to a lower value then it is ignored. Thus leaving it at the default of 0 effectively means to use the regular file quality setting for all saved images. This is to prevent acccidentally saving important images at a worse quality setting.", + type => $types{integer}, + category => "images", + }, + # Deprecated, now stream quality + { + name => "ZM_JPEG_IMAGE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_JPEG_STREAM_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_MPEG_TIMED_FRAMES", + default => "yes", + description => "Tag video frames with a timestamp for more realistic streaming", + help => "When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it's capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it's 'real' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_MPEG_LIVE_FORMAT", + default => "swf", + description => "What format 'live' video streams are played in", + help => "When using MPEG mode ZoneMinder can output live video. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player but I'm currently not sure what, if anything, works on a Linux platform. If you find out please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_MPEG_REPLAY_FORMAT", + default => "swf", + description => "What format 'replay' video streams are played in", + help => "When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player and 'mpg', or 'avi' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_RAND_STREAM", + default => "yes", + description => "Add a random string to prevent caching of streams", + help => "Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_OPT_CAMBOZOLA", + default => "no", + description => "Is the (optional) cambozola java streaming client installed", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_CAMBOZOLA", + default => "cambozola.jar", + description => "Web path to (optional) cambozola java streaming client", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. Leave this as 'cambozola.jar' if cambozola is installed in the same directory as the ZoneMinder web client files.", + requires => [ { name=>"ZM_OPT_CAMBOZOLA", value=>"yes" } ], + type => $types{rel_path}, + category => "images", + }, + { + name => "ZM_RELOAD_CAMBOZOLA", + default => "0", + description => "After how many seconds should Cambozola be reloaded in live view", + help => "Cambozola allows for the viewing of streaming MJPEG however it caches the entire stream into cache space on the computer, setting this to a number > 0 will cause it to automatically reload after that many seconds to avoid filling up a hard drive.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_TIMESTAMP_ON_CAPTURE", + default => "yes", + description => "Timestamp images as soon as they are captured", + help => "ZoneMinder can add a timestamp to images in two ways. The default method, when this option is set, is that each image is timestamped immediately when captured and so the image held in memory is marked right away. The second method does not timestamp the images until they are either saved as part of an event or accessed over the web. The timestamp used in both methods will contain the same time as this is preserved along with the image. The first method ensures that an image is timestamped regardless of any other circumstances but will result in all images being timestamped even those never saved or viewed. The second method necessitates that saved images are copied before being saved otherwise two timestamps perhaps at different scales may be applied. This has the (perhaps) desirable side effect that the timestamp is always applied at the same resolution so an image that has scaling applied will still have a legible and correctly scaled timestamp.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CPU_EXTENSIONS", + default => "yes", + description => "Use advanced CPU extensions to increase performance", + help => "When advanced processor extensions such as SSE2 or SSSE3 are available, ZoneMinder can use them, which should increase performance and reduce system load. Enabling this option on processors that do not support the advanced processors extensions used by ZoneMinder is harmless and will have no effect.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_FAST_IMAGE_BLENDS", + default => "yes", + description => "Use a fast algorithm to blend the reference image", + help => "To detect alarms ZoneMinder needs to blend the captured image with the stored reference image to update it for comparison with the next image. The reference blend percentage specified for the monitor controls how much the new image affects the reference image. There are two methods that are available for this. If this option is set then fast calculation which does not use any multiplication or division is used. This calculation is extremely fast, however it limits the possible blend percentages to 50%, 25%, 12.5%, 6.25%, 3.25% and 1.5%. Any other blend percentage will be rounded to the nearest possible one. The alternative is to switch this option off and use standard blending instead, which is slower.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_ADAPTIVE_SKIP", + default => "yes", + description => "Should frame analysis try and be efficient in skipping frames", + help => "In previous versions of ZoneMinder the analysis daemon would attempt to keep up with the capture daemon by processing the last captured frame on each pass. This would sometimes have the undesirable side-effect of missing a chunk of the initial activity that caused the alarm because the pre-alarm frames would all have to be written to disk and the database before processing the next frame, leading to some delay between the first and second event frames. Setting this option enables a newer adaptive algorithm where the analysis daemon attempts to process as many captured frames as possible, only skipping frames when in danger of the capture daemon overwriting yet to be processed frames. This skip is variable depending on the size of the ring buffer and the amount of space left in it. Enabling this option will give you much better coverage of the beginning of alarms whilst biasing out any skipped frames towards the middle or end of the event. However you should be aware that this will have the effect of making the analysis daemon run somewhat behind the capture daemon during events and for particularly fast rates of capture it is possible for the adaptive algorithm to be overwhelmed and not have time to react to a rapid build up of pending frames and thus for a buffer overrun condition to occur.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_BLEND_ALARMED_IMAGES", + default => "yes", + description => "Blend alarmed images to update the reference image", + help => "To detect alarms ZoneMinder compares an image with a reference image which is formed from a composite of the previous images. This option determines whether images that cause events are included in this process. Doing so may increase the precision of the alarmed region but can cause problems if wholescale lighting changes cause alarms as this would not get fed back into the image and an alarm may persist indefinately. A better way to achive the same effect in most cases is to lower substantially the reference blend percentage in specific monitors.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_MAX_SUSPEND_TIME", + default => "30", + description => "Maximum time that a monitor may have motion detection suspended", + help => "ZoneMinder allows monitors to have motion detection to be suspended, for instance while panning a camera. Ordinarily this relies on the operator resuming motion detection afterwards as failure to do so can leave a monitor in a permanently suspended state. This setting allows you to set a maximum time which a camera may be suspended for before it automatically resumes motion detection. This time can be extended by subsequent suspend indications after the first so continuous camera movement will also occur while the monitor is suspended.", + type => $types{integer}, + category => "config", + }, + # Deprecated, really no longer necessary + { + name => "ZM_OPT_REMOTE_CAMERAS", + default => "no", + description => "Are you going to use remote/networked cameras", + help => "ZoneMinder can work with both local cameras, ie. those attached physically to your computer and remote or network cameras. If you will be using networked cameras select this option.", + type => $types{boolean}, + category => "hidden", + }, + # Deprecated, now set on a per monitor basis using the Method field + { + name => "ZM_NETCAM_REGEXPS", + default => "yes", + description => "Use regular expression matching with network cameras", + help => "Traditionally ZoneMinder has used complex regular regular expressions to handle the multitude of formats that network cameras produce. In versions from 1.21.1 the default is to use a simpler and faster built in pattern matching methodology. This works well with most networks cameras but if you have problems you can try the older, but more flexible, regular expression based method by selecting this option. Note, to use this method you must have libpcre installed on your system.", + requires => [ { name => "ZM_OPT_REMOTE_CAMERAS", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_HTTP_VERSION", + default => "1.1", + description => "The version of HTTP that ZoneMinder will use to connect", + help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.", + type => { db_type=>"string", hint=>"1.1|1.0", pattern=>qr|^(1\.[01])$|, format=>q( $1?$1:"" ) }, + category => "network", + }, + { + name => "ZM_HTTP_UA", + default => "ZoneMinder", + description => "The user agent that ZoneMinder uses to identify itself", + help => "When ZoneMinder communicates with remote cameras it will identify itself using this string and it's version number. This is normally sufficient, however if a particular cameras expects only to communicate with certain browsers then this can be changed to a different string identifying ZoneMinder as Internet Explorer or Netscape etc.", + type => $types{string}, + category => "network", + }, + { + name => "ZM_HTTP_TIMEOUT", + default => "2500", + description => "How long ZoneMinder waits before giving up on images (milliseconds)", + help => "When retrieving remote images ZoneMinder will wait for this length of time before deciding that an image is not going to arrive and taking steps to retry. This timeout is in milliseconds (1000 per second) and will apply to each part of an image if it is not sent in one whole chunk.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MIN_RTP_PORT", + default => "40200", + description => "Minimum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the minimum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MAX_RTP_PORT", + default => "40499", + description => "Maximum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the maximum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting. You should also ensure that you have opened up at least two ports for each monitor that will be connecting to unicasting network cameras.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_OPT_FFMPEG", + default => "yes", + description => "Is the ffmpeg video encoder/decoder installed", + help => "ZoneMinder can optionally encode a series of video images into an MPEG encoded movie file for viewing, downloading or storage. This option allows you to specify whether you have the ffmpeg tools installed. Note that creating MPEG files can be fairly CPU and disk intensive and is not a required option as events can still be reviewed as video streams without it.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_FFMPEG", + default => "/usr/bin/ffmpeg", + description => "Path to (optional) ffmpeg mpeg encoder", + help => "This path should point to where ffmpeg has been installed.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{abs_path}, + category => "images", + }, + { + name => "ZM_FFMPEG_INPUT_OPTIONS", + default => "", + description => "Additional input options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before the -i option). Check the ffmpeg documentation for a full list of options which may be used here.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_OUTPUT_OPTIONS", + default => "-r 25", + description => "Additional output options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after the -i option). Check the ffmpeg documentation for a full list of options which may be used here. The most common one will often be to force an output frame rate supported by the video encoder.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_FORMATS", + default => "mpg mpeg wmv asf avi* mov swf 3gp**", + description => "Formats to allow for ffmpeg video generation", + help => "Ffmpeg can generate video in many different formats. This option allows you to list the ones you want to be able to select. As new formats are supported by ffmpeg you can add them here and be able to use them immediately. Adding a '*' after a format indicates that this will be the default format used for web video, adding '**' defines the default format for phone video.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_LOG_LEVEL_SYSLOG", + default => "0", + description => "Save logging output to the system log", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_FILE", + default => "-5", + description => "Save logging output to component files", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_WEBLOG", + default => "-5", + description => "Save logging output to the weblog", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_DATABASE", + default => "0", + description => "Save logging output to the database", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DATABASE_LIMIT", + default => "7 day", + description => "Maximum number of log entries to retain", + help => "If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as ' day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.", + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG", + default => "no", + description => "Switch debugging on", + help => "ZoneMinder components usually support debug logging available to help with diagnosing problems. Binary components have several levels of debug whereas more other components have only one. Normally this is disabled to minimise performance penalties and avoid filling logs too quickly. This option lets you switch on other options that allow you to configure additional debug information to be output. Components will pick up this instruction when they are restarted.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_TARGET", + default => "", + description => "What components should have extra debug enabled", + help => "There are three scopes of debug available. Leaving this option blank means that all components will use extra debug (not recommended). Setting this option to '_', e.g. _zmc, will limit extra debug to that component only. Setting this option to '__', e.g. '_zmc_m1' will limit extra debug to that instance of the component only. This is ordinarily what you probably want to do. To debug scripts use their names without the .pl extension, e.g. '_zmvideo' and to debug issues with the web interface use '_web'. You can specify multiple targets by separating them with '|' characters.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_LEVEL", + default => 1, + description => "What level of extra debug should be enabled", + help => "There are 9 levels of debug available, with higher numbers being more debug and level 0 being no debug. However not all levels are used by all components. Also if there is debug at a high level it is usually likely to be output at such a volume that it may obstruct normal operation. For this reason you should set the level carefully and cautiously until the degree of debug you wish to see is present. Scripts and the web interface only have one level so this is an on/off type option for them.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => { db_type=>"integer", hint=>"1|2|3|4|5|6|7|8|9", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_FILE", + default => "/tmp/zm/zm_debug.log+", + description => "Where extra debug is output to", + help => "This option allows you to specify a different target for debug output. All components have a default log file which will norally be in /tmp or /var/log and this is where debug will be written to if this value is empty. Adding a path here will temporarily redirect debug, and other logging output, to this file. This option is a simple filename and you are debugging several components then they will all try and write to the same file with undesirable consequences. Appending a '+' to the filename will cause the file to be created with a '.' suffix containing your process id. In this way debug from each run of a component is kept separate. This is the recommended setting as it will also prevent subsequent runs from overwriting the same log. You should ensure that permissions are set up to allow writing to the file and directory specified here.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_CHECK_PERIOD", + default => "900", + description => "Time period used when calculating overall system health", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to indicate what period of historical events are used in this calculation. This value is expressed in seconds and is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_WAR_COUNT", + default => "1", + description => "Number of warnings indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alert state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_ERR_COUNT", + default => "1", + description => "Number of errors indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alert state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_FAT_COUNT", + default => "0", + description => "Number of fatal error indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alert state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_WAR_COUNT", + default => "100", + description => "Number of warnings indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alarm state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_ERR_COUNT", + default => "10", + description => "Number of errors indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alarm state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_FAT_COUNT", + default => "1", + description => "Number of fatal error indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alarm state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_RECORD_EVENT_STATS", + default => "yes", + description => "Record event statistical information, switch off if too slow", + help => "This version of ZoneMinder records detailed information about events in the Stats table. This can help in profiling what the optimum settings are for Zones though this is tricky at present. However in future releases this will be done more easily and intuitively, especially with a large sample of events. The default option of 'yes' allows this information to be collected now in readiness for this but if you are concerned about performance you can switch this off in which case no Stats information will be saved.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_RECORD_DIAG_IMAGES", + default => "no", + description => "Record intermediate alarm diagnostic images, can be very slow", + help => "In addition to recording event statistics you can also record the intermediate diagnostic images that display the results of the various checks and processing that occur when trying to determine if an alarm event has taken place. There are several of these images generated for each frame and zone for each alarm or alert frame so this can have a massive impact on performance. Only switch this setting on for debug or analysis purposes and remember to switch it off again once no longer required.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_DUMP_CORES", + default => "no", + description => "Create core files on unexpected process failure.", + help => "When an unrecoverable error occurs in a ZoneMinder binary process is has traditionally been trapped and the details written to logs to aid in remote analysis. However in some cases it is easier to diagnose the error if a core file, which is a memory dump of the process at the time of the error, is created. This can be interactively analysed in the debugger and may reveal more or better information than that available from the logs. This option is recommended for advanced users only otherwise leave at the default. Note using this option to trigger core files will mean that there will be no indication in the binary logs that a process has died, they will just stop, however the zmdc log will still contain an entry. Also note that you may have to explicitly enable core file creation on your system via the 'ulimit -c' command or other means otherwise no file will be created regardless of the value of this option.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_PATH_MAP", + default => "/dev/shm", + description => "Path to the mapped memory files that that ZoneMinder can use", + help => "ZoneMinder has historically used IPC shared memory for shared data between processes. This has it's advantages and limitations. This version of ZoneMinder can use an alternate method, mapped memory, instead with can be enabled with the --enable--mmap directive to configure. This requires less system configuration and is generally more flexible. However it requires each shared data segment to map onto a filesystem file. This option indicates where those mapped files go. You should ensure that this location has sufficient space for these files and for the best performance it should be a tmpfs file system or ramdisk otherwise disk access may render this method slower than the regular shared memory one.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SOCKS", + default => "/tmp/zm", + description => "Path to the various Unix domain socket files that ZoneMinder uses", + help => "ZoneMinder generally uses Unix domain sockets where possible. This reduces the need for port assignments and prevents external applications from possibly compromising the daemons. However each Unix socket requires a .sock file to be created. This option indicates where those socket files go.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_LOGS", + default => "/var/log/zm", + description => "Path to the various logs that the ZoneMinder daemons generate", + help => "There are various daemons that are used by ZoneMinder to perform various tasks. Most generate helpful log files and this is where they go. They can be deleted if not required for debugging.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SWAP", + default => "/tmp/zm", + description => "Path to location for temporary swap images used in streaming", + help => "Buffered playback requires temporary swap images to be stored for each instance of the streaming daemons. This option determines where these images will be stored. The images will actually be stored in sub directories beneath this location and will be automatically cleaned up after a period of time.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_WEB_TITLE_PREFIX", + default => "ZM", + description => "The title prefix displayed on each window", + help => "If you have more than one installation of ZoneMinder it can be helpful to display different titles for each one. Changing this option allows you to customise the window titles to include further information to aid identification.", + type => $types{string}, + category => "web", + }, + { + name => "ZM_WEB_RESIZE_CONSOLE", + default => "yes", + description => "Should the console window resize itself to fit", + help => "Traditionally the main ZoneMinder web console window has resized itself to shrink to a size small enough to list only the monitors that are actually present. This is intended to make the window more unobtrusize but may not be to everyones tastes, especially if opened in a tab in browsers which support this kind if layout. Switch this option off to have the console window size left to the users preference", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_POPUP_ON_ALARM", + default => "yes", + description => "Should the monitor window jump to the top if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to pop to the front if an alarm occurs when the window is minimised or behind another window. This is most useful if your monitors are over doors for example when they can pop up if someone comes to the doorway.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_X10", + default => "no", + description => "Support interfacing with X10 devices", + help => "If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.", + type => $types{boolean}, + category => "x10", + }, + { + name => "ZM_X10_DEVICE", + default => "/dev/ttyS0", + description => "What device is your X10 controller connected on", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.", + type => $types{abs_path}, + category => "x10", + }, + { + name => "ZM_X10_HOUSE_CODE", + default => "A", + description => "What X10 house code should be used", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.", + type => { db_type=>"string", hint=>"A-P", pattern=>qr|^([A-P])|i, format=>q( uc($1) ) }, + category => "x10", + }, + { + name => "ZM_X10_DB_RELOAD_INTERVAL", + default => "60", + description => "How often (in seconds) the X10 daemon reloads the monitors from the database", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "The zmx10 daemon periodically checks the database to find out what X10 events trigger, or result from, alarms. This option determines how frequently this check occurs, unless you change this area frequently this can be a fairly large value.", + type => $types{integer}, + category => "x10", + }, + { + name => "ZM_WEB_SOUND_ON_ALARM", + default => "no", + description => "Should the monitor window play a sound if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to play a sound to alert you if an alarm occurs.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_ALARM_SOUND", + default => "", + description => "The sound to play on alarm, put this in the sounds directory", + help => "You can specify a sound file to play if an alarm occurs whilst you are watching a live monitor stream. So long as your browser understands the format it does not need to be any particular type. This file should be placed in the sounds directory defined earlier.", + type => $types{file}, + requires => [ { name => "ZM_WEB_SOUND_ON_ALARM", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_COMPACT_MONTAGE", + default => "no", + description => "Compact the montage view by removing extra detail", + help => "The montage view shows the output of all of your active monitors in one window. This include a small menu and status information for each one. This can increase the web traffic and make the window larger than may be desired. Setting this option on removes all this extraneous information and just displays the images.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_FAST_DELETE", + default => "yes", + description => "Delete only event database records for speed", + help => "Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if your are trying to do a lot of events at once. It is recommended that you set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_STRICT_VIDEO_CONFIG", + default => "yes", + description => "Allow errors in setting video config to be fatal", + help => "With some video devices errors can be reported in setting the various video attributes when in fact the operation was successful. Switching this option off will still allow these errors to be reported but will not cause them to kill the video capture daemon. Note however that doing this will cause all errors to be ignored including those which are genuine and which may cause the video capture to not function correctly. Use this option with caution.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_SIGNAL_CHECK_POINTS", + default => "10", + description => "How many points in a captured image to check for signal loss", + help => "For locally attached video cameras ZoneMinder can check for signal loss by looking at a number of random points on each captured image. If all of these points are set to the same fixed colour then the camera is assumed to have lost signal. When this happens any open events are closed and a short one frame signal loss event is generated, as is another when the signal returns. This option defines how many points on each image to check. Note that this is a maximum, any points found to not have the check colour will abort any further checks so in most cases on a couple of points will actually be checked. Network and file based cameras are never checked.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_V4L_MULTI_BUFFER", + default => "yes", + description => "Use more than one buffer for Video 4 Linux devices", + help => "Performance when using Video 4 Linux devices is usually best if multiple buffers are used allowing the next image to be captured while the previous one is being processed. If you have multiple devices on a card sharing one input that requires switching then this approach can sometimes cause frames from one source to be mixed up with frames from another. Switching this option off prevents multi buffering resulting in slower but more stable image capture. This option is ignored for non-local cameras or if only one input is present on a capture chip. This option addresses a similar problem to the ZM_CAPTURES_PER_FRAME option and you should normally change the value of only one of the options at a time.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CAPTURES_PER_FRAME", + default => "1", + description => "How many images are captured per returned frame, for shared local cameras", + help => "If you are using cameras attached to a video capture card which forces multiple inputs to share one capture chip, it can sometimes produce images with interlaced frames reversed resulting in poor image quality and a distinctive comb edge appearance. Increasing this setting allows you to force additional image captures before one is selected as the captured frame. This allows the capture hardware to 'settle down' and produce better quality images at the price of lesser capture rates. This option has no effect on (a) network cameras, or (b) where multiple inputs do not share a capture chip. This option addresses a similar problem to the ZM_V4L_MULTI_BUFFER option and you should normally change the value of only one of the options at a time.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_FILTER_RELOAD_DELAY", + default => "300", + description => "How often (in seconds) filters are reloaded in zmfilter", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are reloaded from the database to get the latest versions or new filters. If you don't change filters very often this value can be set to a large value.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FILTER_EXECUTE_INTERVAL", + default => "60", + description => "How often (in seconds) to run automatic saved filters", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are executed on the saved event in the database. If you want a rapid response to new events this should be a smaller value, however this may increase the overall load on the system and affect performance of other elements.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_UPLOAD", + default => "no", + description => "Should ZoneMinder support uploading events from filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should be uploaded to a remote server for archiving. This option specifies whether this functionality should be available", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_FORMAT", + default => "tar", + description => "What format the uploaded events should be created in.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "Uploaded events may be stored in either .tar or .zip format, this option specifies which. Note that to use this you will need to have the Archive::Tar and/or Archive::Zip perl modules installed.", + type => { db_type=>"string", hint=>"tar|zip", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^t/ ? "tar" : "zip" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_COMPRESS", + default => "no", + description => "Should archive files be compressed", + help => "When the archive files are created they can be compressed. However in general since the images are compressed already this saves only a minimal amount of space versus utilising more CPU in their creation. Only enable if you have CPU to waste and are limited in disk space on your remote server or bandwidth.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_ANALYSE", + default => "no", + description => "Include the analysis files in the archive", + help => "When the archive files are created they can contain either just the captured frames or both the captured frames and, for frames that caused an alarm, the analysed image with the changed area highlighted. This option controls files are included. Only include analysed frames if you have a high bandwidth connection to the remote server or if you need help in figuring out what caused an alarm in the first place as archives with these files in can be considerably larger.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PROTOCOL", + default => "ftp", + description => "What protocol to use to upload events", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "ZoneMinder can upload events to a remote server using either FTP or SFTP. Regular FTP is widely supported but not necessarily very secure whereas SFTP (Secure FTP) runs over an ssh connection and so is encrypted and uses regular ssh ports. Note that to use this you will need to have the appropriate perl module, either Net::FTP or Net::SFTP installed depending on your choice.", + type => { db_type=>"string", hint=>"ftp|sftp", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^f/ ? "ftp" : "sftp" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_HOST", + default => "", + description => "The remote server to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_HOST", + default => "", + description => "The remote server to upload events to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PORT", + default => "", + description => "The port on the remote upload server, if not the default (SFTP only)", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are using the SFTP protocol then this option allows you to specify a particular port to use for connection. If this option is left blank then the default, port 22, is used. This option is ignored for FTP uploads.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_USER", + default => "", + description => "Your ftp username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the username that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_USER", + default => "", + description => "Remote server username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASS", + default => "", + description => "Your ftp password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the password that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_PASS", + default => "", + description => "Remote server password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_LOC_DIR", + default => "/tmp/zm", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_LOC_DIR", + default => "/tmp/zm", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the maximum ftp inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the maximum inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASSIVE", + default => "yes", + description => "Use passive ftp when uploading", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates that ftp transfers should be done in passive mode. This uses a single connection for all ftp activity and, whilst slower than active transfers, is more robust and likely to work from behind filewalls. This option is ignored for SFTP transfers.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "If your computer is behind a firewall or proxy you may need to set FTP to passive mode. In fact for simple transfers it makes little sense to do otherwise anyway but you can set this to 'No' if you wish.", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_DEBUG", + default => "no", + description => "Switch ftp debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be included in the zmfilter log file.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_DEBUG", + default => "no", + description => "Switch upload debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be generated by the underlying transfer modules and included in the logs.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_OPT_EMAIL", + default => "no", + description => "Should ZoneMinder email you details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details emailed to you at a designated email address. This will allow you to be notified of events as soon as they occur and also to quickly view the events directly. This option specifies whether this functionality should be available. The email created with this option can be any size and is intended to be sent to a regular email reader rather than a mobile device.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_EMAIL_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)" +body = " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder"', + description => "The text of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_EMAIL_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)", + description => "The subject of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the subject of the email that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_EMAIL_BODY", + default => " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder", + description => "The body of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_OPT_MESSAGE", + default => "no", + description => "Should ZoneMinder message you with details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details sent to you at a designated short message email address. This will allow you to be notified of events as soon as they occur. This option specifies whether this functionality should be available. The email created by this option will be brief and is intended to be sent to an SMS gateway or a minimal mail reader such as a mobile device or phone rather than a regular email reader.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_MESSAGE_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the short message email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_MESSAGE_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI%" +body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score."', + description => "The text of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_MESSAGE_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI%", + description => "The subject of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the subject of the message that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_MESSAGE_BODY", + default => "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.", + description => "The body of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_NEW_MAIL_MODULES", + default => "no", + description => "Use a newer perl method to send emails", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "Traditionally ZoneMinder has used the MIME::Entity perl module to construct and send notification emails and messages. Some people have reported problems with this module not being present at all or flexible enough for their needs. If you are one of those people this option allows you to select a new mailing method using MIME::Lite and Net::SMTP instead. This method was contributed by Ross Melin and should work for everyone but has not been extensively tested so currently is not selected by default.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_HOST", + default => "localhost", + description => "The host address of your SMTP mail server", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "If you have chosen SMTP as the method by which to send notification emails or messages then this option allows you to choose which SMTP server to use to send them. The default of localhost may work if you have the sendmail, exim or a similar daemon running however you may wish to enter your ISP's SMTP mail server here.", + type => $types{hostname}, + category => "mail", + }, + { + name => "ZM_FROM_EMAIL", + default => "", + description => "The email address you wish your event notifications to originate from", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can appear to come from a designated email address to help you with mail filtering etc. An address of something like ZoneMinder\@your.domain is recommended.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_URL", + default => "", + description => "The URL of your ZoneMinder installation", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. http://host.your.domain/zm.php.", + type => $types{url}, + category => "mail", + }, + { + name => "ZM_MAX_RESTART_DELAY", + default => "600", + description => "Maximum delay (in seconds) for daemon restart attempts.", + help => "The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_CHECK_INTERVAL", + default => "10", + description => "How often to check the capture daemons have not locked up", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_MAX_DELAY", + default => "5", + description => "The maximum delay allowed since the last captured image", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.", + type => $types{decimal}, + category => "system", + }, + { + + name => "ZM_RUN_AUDIT", + default => "yes", + description => "Run zmaudit to check data consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.", + type => $types{boolean}, + category => "system", + }, + { + + name => "ZM_AUDIT_CHECK_INTERVAL", + default => "900", + description => "How often to check database and filesystem consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FORCED_ALARM_SCORE", + default => "255", + description => "Score to give forced alarms", + help => "The 'zmu' utility can be used to force an alarm on a monitor rather than rely on the motion detection algorithms. This option determines what score to give these alarms to distinguish them from regular ones. It must be 255 or less.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_BULK_FRAME_INTERVAL", + default => "100", + description => "How often a bulk frame should be written to the database", + help => "Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation ('Record' or 'Mocord' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one 'bulk' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_EVENT_CLOSE_MODE", + default => "idle", + description => "When continuous events are closed.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.", + type => $types{boolean}, + type => { db_type=>"string", hint=>"time|idle|alarm", pattern=>qr|^([tia])|i, format=>q( ($1 =~ /^t/) ? "time" : ($1 =~ /^i/ ? "idle" : "time" ) ) }, + category => "config", + }, + # Deprecated, superseded by event close mode + { + name => "ZM_FORCE_CLOSE_EVENTS", + default => "no", + description => "Close events at section ends.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section and ordinarily this will prevent the event being closed until the motion has ceased. Switching this option on will force the event closed at the specified time regardless of any motion activity.", + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_CREATE_ANALYSIS_IMAGES", + default => "yes", + description => "Create analysed alarm images with motion outlined", + help => "By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_WEIGHTED_ALARM_CENTRES", + default => "no", + description => "Use a weighted algorithm to calculate the centre of an alarm", + help => "ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_EVENT_IMAGE_DIGITS", + default => "3", + description => "How many significant digits are used in event image numbering", + help => "As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_DEFAULT_ASPECT_RATIO", + default => "4:3", + description => "The default width:height aspect ratio used in monitors", + help => "When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format : and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.", + type => $types{string}, + category => "config", + }, + { + name => "ZM_USER_SELF_EDIT", + default => "no", + description => "Allow unprivileged users to change their details", + help => "Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_FRAME_SERVER", + default => "no", + description => "Should analysis farm out the writing of images to disk", + #requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ], + help => "In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_FRAME_SOCKET_SIZE", + default => "0", + description => "Specify the frame server socket buffer size if non-standard", + requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ], + help => "For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_CONTROL", + default => "no", + description => "Support controllable (e.g. PTZ) cameras", + help => "ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_OPT_TRIGGERS", + default => "no", + description => "Interface external event triggers via socket or device files", + help => "ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_CHECK_FOR_UPDATES", + default => "yes", + description => "Check with zoneminder.com for updated versions", + help => "From ZoneMinder version 1.17.0 onwards new versions are expected to be more frequent. To save checking manually for each new version ZoneMinder can check with the zoneminder.com website to determine the most recent release. These checks are infrequent, about once per week, and no personal or system information is transmitted other than your current version number. If you do not wish these checks to take place or your ZoneMinder system has no internet access you can switch these check off with this configuration variable", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_UPDATE_CHECK_PROXY", + default => "", + description => "Proxy url if required to access zoneminder.com", + help => "If you use a proxy to access the internet then ZoneMinder needs to know so it can access zoneminder.com to check for updates. If you do use a proxy enter the full proxy url here in the form of http://:/", + type => $types{string}, + category => "system", + }, + { + name => "ZM_SHM_KEY", + default => "0x7a6d0000", + description => "Shared memory root key to use", + help => "ZoneMinder uses shared memory to speed up communication between modules. To identify the right area to use shared memory keys are used. This option controls what the base key is, each monitor will have it's Id or'ed with this to get the actual key used. You will not normally need to change this value unless it clashes with another instance of ZoneMinder on the same machine. Only the first four hex digits are used, the lower four will be masked out and ignored.", + type => $types{hexadecimal}, + category => "system", + }, + # Deprecated, really no longer necessary + { + name => "ZM_WEB_REFRESH_METHOD", + default => "javascript", + description => "What method windows should use to refresh themselves", + help => "Many windows in Javascript need to refresh themselves to keep their information current. This option determines what method they should use to do this. Choosing 'javascript' means that each window will have a short JavaScript statement in with a timer to prompt the refresh. This is the most compatible method. Choosing 'http' means the refresh instruction is put in the HTTP header. This is a cleaner method but refreshes are interrupted or cancelled when a link in the window is clicked meaning that the window will no longer refresh and this would have to be done manually.", + type => { db_type=>"string", hint=>"javascript|http", pattern=>qr|^([jh])|i, format=>q( $1 =~ /^j/ ? "javascript" : "http" ) }, + category => "hidden", + }, + { + name => "ZM_WEB_EVENT_SORT_FIELD", + default => "DateTime", + description => "Default field the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what field is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"Id|Name|Cause|MonitorName|DateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore", pattern=>qr|.|, format=>q( $1 ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENT_SORT_ORDER", + default => "asc", + description => "Default order the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what order (ascending or descending) is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"asc|desc", pattern=>qr|^([ad])|i, format=>q( $1 =~ /^a/i ? "asc" : "desc" ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENTS_PER_PAGE", + default => "25", + description => "How many events to list per page in paged mode", + help => "In the event list view you can either list all events or just a page at a time. This option controls how many events are listed per page in paged mode and how often to repeat the column headers in non-paged mode.", + type => $types{integer}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMBS", + default => "no", + description => "Display mini-thumbnails of event images in event lists", + help => "Ordinarily the event lists just display text details of the events to save space and time. By switching this option on you can also display small thumbnails to help you identify events of interest. The size of these thumbnails is controlled by the following two options.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_WIDTH", + default => "48", + description => "The width of the thumbnails that appear in the event lists", + help => "This options controls the width of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a height instead in the next option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_HEIGHT", + default => "0", + description => "The height of the thumbnails that appear in the event lists", + help => "This options controls the height of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a width instead in the previous option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_USE_OBJECT_TAGS", + default => "yes", + description => "Wrap embed in object tags for media content", + help => "There are two methods of including media content in web pages. The most common way is use the EMBED tag which is able to give some indication of the type of content. However this is not a standard part of HTML. The official method is to use OBJECT tags which are able to give more information allowing the correct media viewers etc to be loaded. However these are less widely supported and content may be specifically tailored to a particular platform or player. This option controls whether media content is enclosed in EMBED tags only or whether, where appropriate, it is additionally wrapped in OBJECT tags. Currently OBJECT tags are only used in a limited number of circumstances but they may become more widespread in the future. It is suggested that you leave this option on unless you encounter problems playing some content.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_H_REFRESH_MAIN", + default => "300", + introduction => "There are now a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client.\n\nThe next few options control what happens when the client is running in 'high' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a local network or high speed link. In most cases the default values will be suitable as a starting point.", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_CYCLE", + default => "10", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_IMAGE", + default => "5", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_STATUS", + default => "3", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_EVENTS", + default => "30", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "highband", + }, + { + name => "ZM_WEB_H_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_BITRATE", + default => "150000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_MAXFPS", + default => "15", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_SCALE_THUMBS", + default => "no", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_AJAX_TIMEOUT", + default => "3000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_M_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + introduction => "The next few options control what happens when the client is running in 'medium' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a slower cable or DSL link. In most cases the default values will be suitable as a starting point.", + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_CYCLE", + default => "20", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_IMAGE", + default => "10", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_STATUS", + default => "5", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_EVENTS", + default => "60", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "medband", + }, + { + name => "ZM_WEB_M_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_BITRATE", + default => "75000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_MAXFPS", + default => "10", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_AJAX_TIMEOUT", + default => "5000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_L_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + introduction => "The next few options control what happens when the client is running in 'low' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a modem or slow link. In most cases the default values will be suitable as a starting point.", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_CYCLE", + default => "30", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_IMAGE", + default => "15", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_STATUS", + default => "10", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_EVENTS", + default => "180", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "lowband", + }, + { + name => "ZM_WEB_L_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_BITRATE", + default => "25000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_SHOW_PROGRESS", + default => "no", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_P_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_BITRATE", + default => "8000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_DYN_LAST_VERSION", + default => "", + description => "What the last version of ZoneMinder recorded from zoneminder.com is", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_CURR_VERSION", + default => "1.25.0", + description => "What the effective current version of ZoneMinder is, might be different from actual if versions ignored", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DB_VERSION", + default => "1.25.0", + description => "What the version of the database is, from zmupdate", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_LAST_CHECK", + default => "", + description => "When the last check for version from zoneminder.com was", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_NEXT_REMINDER", + default => "", + description => "When the earliest time to remind about versions will be", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DONATE_REMINDER_TIME", + default => 0, + description => "When the earliest time to remind about donations will be", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_SHOW_DONATE_REMINDER", + default => "yes", + description => "Remind about donations or not", + help => "", + type => $types{boolean}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_EYEZM_DEBUG", + default => "no", + description => "Switch additional debugging on for eyeZm Plugin", + help => "Enable or Disable extra debugging from the eyeZm Plugin. Extra debugging information will be displayed in it's own file (EYEZM_LOG_TO_FILE is set), or your Apache error log", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_TO_FILE", + default => "yes", + description => "When eyeZm Debugging is enabled, enabling this logs output to it's own file", + help => "When EYEZM_DEBUG is on and EYEZM_LOG_TO_FILE is on, output generated from the eyeZm Plugin will go to it's own file. Otherwise it will go to the apache error log.", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_FILE", + default => "/var/log/zm/zm_xml.log", + description => "Default filename to use when logging eyeZm Output and EYEZM_LOG_TO_FILE is enabled", + help => "This file will contain it's own output from the eyeZm Plugin when EYEZM_LOG_TO_FILE and EYEZM_DEBUG are both enabled", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_EVENT_VCODEC", + default => "mpeg4", + description => "Default video-codec to use for encoding events", + help => "The eyeZm Plugin calls FFMPEG externally to encode the captured images. If your FFMPEG is not built with support for H264, change this to MPEG-4. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+).", + type => { db_type=>"string", hint=>"mpeg4|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mpeg4" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_FEED_VCODEC", + default => "mjpeg", + description => "Default video-codec to use for streaming the live feed", + help => "Determines whether the live stream is generated using native MJPEG streaming with ZoneMinder, or H264 using FFMPEG and HTML-5 streaming. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+). This is just a default parameter, and can be overridden with eyeZm.", + type => { db_type=>"string", hint=>"mjpeg|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mjpeg" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_BR", + default => "96k", + description => "Default bit-rate to use with FFMPEG for H264 streaming", + help => "When using the eyeZm Plugin to stream H264 data, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_EVBR", + default => "128k", + description => "Default bit-rate to use with FFMPEG for H264 event viewing", + help => "When using the eyeZm Plugin to view events in H264, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_TIMEOUT", + default => "20", + description => "Timeout (sec) to wait for H264 stream to start before terminating", + help => "The eyeZm Plugin will attempt to spawn an H264 stream when requested, and require that it complete within the timeout specified. If you have a slow system or find through the logs that the H264 stream is not starting because the timeout is expiring, even though FFMPEG is running, try increasing this value. If you have a fast system, decreasing this value can improve the responsiveness when there are issues starting H264 streams", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_SEG_DURATION", + default => "3", + description => "Segment duration used for streaming using HTTP-5 Streaming protocol", + help => "The HTTP-5 Live Streaming Protocol segments the input video stream into small chunks of a duration specified by this parameter. Increasing the segment duration will help with choppy connections on the other end, but will increase the latency in starting a stream.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_PATH_PLUGINS", + default => "/usr/share/zm", + description => "Path to the plugin folder", + help => "3d-party plugins have to be placed here.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PLUGIN_EXTENSION", + default => ".zmpl", + description => "Default extension of plugins to found.", + help => "Default extension of plugins to found.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_PLUGINS_CONFIG_PATH", + default => "/usr/share/zm/plugins.conf", + description => "Path to the config file for plugins.", + help => "Path to the config file for plugins.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_LOAD_PLUGINS", + default => "no", + description => "Load and use 3d-party plugins", + help => "3d-party plugins will be loaded and used for analysing.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_TURNOFF_NATIVE_ANALYSIS", + default => "no", + description => "Turn native ZM\'s image analysis possibility off", + help => "Image analysis with ZM\'s motion detected function will be turned off. Only detection functions from loaded plugins will be used. Note, that if no plugins have be loaded, no detection will be done.", + type => $types{boolean}, + category => "config", + }, + +); + +our %options_hash = map { ( $_->{name}, $_ ) } @options; + +# This function should never need to be called explicitly, except if +# this module is 'require'd rather than 'use'd. See zmconfgen.pl. +sub initialiseConfig +{ + return if ( $configInitialised ); + + # Do some initial data munging to finish the data structures + # Create option ids + my $option_id = 0; + foreach my $option ( @options ) + { + if ( defined($option->{default}) ) + { + $option->{value} = $option->{default} + } + else + { + $option->{value} = ''; + } + #next if ( $option->{category} eq 'hidden' ); + $option->{id} = $option_id++; + } + $configInitialised = 1; +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigData - ZoneMinder Configuration Data module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigData; + use ZoneMinder::ConfigData qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigData module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in new file mode 100644 index 000000000..c835626c6 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -0,0 +1,2056 @@ +# ========================================================================== +# +# ZoneMinder Config Data Module, $Date: 2011-01-20 18:49:42 +0000 (Thu, 20 Jan 2011) $, $Revision: 3230 $ +# 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigData; + +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 = ( + 'data' => [ qw( + %types + @options + %options_hash + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'data'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Data +# +# ========================================================================== + +use Carp; + +our $configInitialised = 0; + +sub INIT +{ + initialiseConfig(); +} + +# Types +our %types = +( + string => { db_type=>"string", hint=>"string", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + alphanum => { db_type=>"string", hint=>"alphanumeric", pattern=>qr|^([a-zA-Z0-9-_]+)$|, format=>q( $1 ) }, + text => { db_type=>"text", hint=>"free text", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + boolean => { db_type=>"boolean", hint=>"yes|no", pattern=>qr|^([yn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : "no" ) }, + integer => { db_type=>"integer", hint=>"integer", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + decimal => { db_type=>"decimal", hint=>"decimal", pattern=>qr|^(\d+(?:\.\d+)?)$|, format=>q( $1 ) }, + hexadecimal => { db_type=>"hexadecimal", hint=>"hexadecimal", pattern=>qr|^(?:0x)?([0-9a-f]{1,8})$|, format=>q( "0x".$1 ) }, + tristate => { db_type=>"string", hint=>"auto|yes|no", pattern=>qr|^([ayn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : ($1 =~ /^n/ ? "no" : "auto" ) ) }, + abs_path => { db_type=>"string", hint=>"/absolute/path/to/somewhere", pattern=>qr|^((?:/[^/]*)+?)/?$|, format=>q( $1 ) }, + rel_path => { db_type=>"string", hint=>"relative/path/to/somewhere", pattern=>qr|^((?:[^/].*)?)/?$|, format=>q( $1 ) }, + directory => { db_type=>"string", hint=>"directory", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + file => { db_type=>"string", hint=>"filename", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + hostname => { db_type=>"string", hint=>"host.your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)$|, format=>q( $1 ) }, + url => { db_type=>"string", hint=>"http://host.your.domain/", pattern=>qr|^(?:http://)?(.+)$|, format=>q( "http://".$1 ) }, + email => { db_type=>"string", hint=>"your.name\@your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$|, format=>q( $1\@$2 ) }, +); + +our @options = +( + { + name => "ZM_LANG_DEFAULT", + default => "en_gb", + description => "Default language used by web interface", + help => "ZoneMinder allows the web interface to use languages other than English if the appropriate language file has been created and is present. This option allows you to change the default language that is used from the shipped language, British English, to another language", + type => $types{string}, + category => "system", + }, + { + name => "ZM_OPT_USE_AUTH", + default => "no", + description => "Authenticate user logins to ZoneMinder", + help => "ZoneMinder can run in two modes. The simplest is an entirely unauthenticated mode where anyone can access ZoneMinder and perform all tasks. This is most suitable for installations where the web server access is limited in other ways. The other mode enables user accounts with varying sets of permissions. Users must login or authenticate to access ZoneMinder and are limited by their defined permissions.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_TYPE", + default => "builtin", + description => "What is used to authenticate ZoneMinder users", + help => "ZoneMinder can use two methods to authenticate users when running in authenticated mode. The first is a builtin method where ZoneMinder provides facilities for users to log in and maintains track of their identity. The second method allows interworking with other methods such as http basic authentication which passes an independently authentication 'remote' user via http. In this case ZoneMinder would use the supplied user without additional authentication provided such a user is configured ion ZoneMinder.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"builtin|remote", pattern=>qr|^([br])|i, format=>q( $1 =~ /^b/ ? "builtin" : "remote" ) }, + category => "system", + }, + { + name => "ZM_AUTH_RELAY", + default => "hashed", + description => "Method used to relay authentication information", + help => "When ZoneMinder is running in authenticated mode it can pass user details between the web pages and the back end processes. There are two methods for doing this. This first is to use a time limited hashed string which contains no direct username or password details, the second method is to pass the username and passwords around in plaintext. This method is not recommend except where you do not have the md5 libraries available on your system or you have a completely isolated system with no external access. You can also switch off authentication relaying if your system is isolated in other ways.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"hashed|plain|none", pattern=>qr|^([hpn])|i, format=>q( ($1 =~ /^h/) ? "hashed" : ($1 =~ /^p/ ? "plain" : "none" ) ) }, + category => "system", + }, + { + name => "ZM_AUTH_HASH_SECRET", + default => "...Change me to something unique...", + description => "Secret for encoding hashed authentication information", + help => "When ZoneMinder is running in hashed authenticated mode it is necessary to generate hashed strings containing encrypted sensitive information such as usernames and password. Although these string are reasonably secure the addition of a random secret increases security substantially.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{string}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_IPS", + default => "yes", + description => "Include IP addresses in the authentication hash", + help => "When ZoneMinder is running in hashed authenticated mode it can optionally include the requesting IP address in the resultant hash. This adds an extra level of security as only requests from that address may use that authentication key. However in some circumstances, such as access over mobile networks, the requesting address can change for each request which will cause most requests to fail. This option allows you to control whether IP addresses are included in the authentication hash on your system. If you experience intermitent problems with authentication, switching this option off may help.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_LOGINS", + default => "no", + description => "Allow login by authentication hash", + help => "The normal process for logging into ZoneMinder is via the login screen with username and password. In some circumstances it may be desirable to allow access directly to one or more pages, for instance from a third party application. If this option is enabled then adding an 'auth' parameter to any request will include a shortcut login bypassing the login screen, if not already logged in. As authentication hashes are time and, optionally, IP limited this can allow short-term access to ZoneMinder screens from other web pages etc. In order to use this the calling application will hae to generate the authentication hash itself and ensure it is valid. If you use this option you should ensure that you have modified the ZM_AUTH_HASH_SECRET to somethign unique to your system.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_DIR_EVENTS", + default => "events", + description => "Directory where events are stored", + help => "This is the path to the events directory where all the event images and other miscellaneous files are stored. It is normally given as a subdirectory of the web directory you have specified earlier however if disk space is tight it can reside on another partition in which case you should create a link from that area to the path you give here.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_USE_DEEP_STORAGE", + default => "yes", + description => "Use a deep filesystem hierarchy for events", + help => "Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date.", + type => $types{boolean}, + category => "paths", + }, + { + name => "ZM_DIR_IMAGES", + default => "images", + description => "Directory where the images that the ZoneMinder client generates are stored", + help => "ZoneMinder generates a myriad of images, mosty of which are associated with events. For those that aren't this is where they go.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_DIR_SOUNDS", + default => "sounds", + description => "Directory to the sounds that the ZoneMinder client can use", + help => "ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where (relative to the web root) to look for this file.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_PATH_ZMS", + default => "/cgi-bin/nph-zms", + description => "Web path to zms streaming server", + help => "The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing 'zms' to 'nph-zms'.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_COLOUR_JPEG_FILES", + default => "yes", + description => "Colourise greyscale JPEG files", + help => "Cameras that capture in greyscale can write their captured images to jpeg files with a corresponding greyscale colour space. This saves a small amount of disk space over colour ones. However some tools such as ffmpeg either fail to work with this colour space or have to convert it beforehand. Setting this option to yes uses up a little more space but makes creation of MPEG files much faster.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_ADD_JPEG_COMMENTS", + default => "no", + description => "Add jpeg timestamp annotations as file header comments", + help => "JPEG files may have a number of extra fields added to the file header. The comment field may have any kind of text added. This options allows you to have the same text that is used to annotate the image additionally included as a file header comment. If you archive event images to other locations this may help you locate images for particular events or times if you use software that can read comment headers.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_JPEG_FILE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the saved event files (1-100)", + help => "When ZoneMinder detects an event it will save the images associated with that event to files. These files are in the JPEG format and can be viewed or streamed later. This option specifies what image quality should be used to save these files. A higher number means better quality but less compression so will take up more disk space and take longer to view over a slow connection. By contrast a low number means smaller, quicker to view, files but at the price of lower quality images. This setting applies to all images written except if the capture image has caused an alarm and the alarm file quality option is set at a higher value when that is used instead.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_JPEG_ALARM_FILE_QUALITY", + default => "0", + description => "Set the JPEG quality setting for the saved event files during an alarm (1-100)", + help => "This value is equivalent to the regular jpeg file quality setting above except that it only applies to images saved while in an alarm state and then only if this value is set to a higher quality setting than the ordinary file setting. If set to a lower value then it is ignored. Thus leaving it at the default of 0 effectively means to use the regular file quality setting for all saved images. This is to prevent acccidentally saving important images at a worse quality setting.", + type => $types{integer}, + category => "images", + }, + # Deprecated, now stream quality + { + name => "ZM_JPEG_IMAGE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_JPEG_STREAM_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_MPEG_TIMED_FRAMES", + default => "yes", + description => "Tag video frames with a timestamp for more realistic streaming", + help => "When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it's capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it's 'real' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_MPEG_LIVE_FORMAT", + default => "swf", + description => "What format 'live' video streams are played in", + help => "When using MPEG mode ZoneMinder can output live video. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player but I'm currently not sure what, if anything, works on a Linux platform. If you find out please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_MPEG_REPLAY_FORMAT", + default => "swf", + description => "What format 'replay' video streams are played in", + help => "When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player and 'mpg', or 'avi' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_RAND_STREAM", + default => "yes", + description => "Add a random string to prevent caching of streams", + help => "Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_OPT_CAMBOZOLA", + default => "no", + description => "Is the (optional) cambozola java streaming client installed", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_CAMBOZOLA", + default => "cambozola.jar", + description => "Web path to (optional) cambozola java streaming client", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. Leave this as 'cambozola.jar' if cambozola is installed in the same directory as the ZoneMinder web client files.", + requires => [ { name=>"ZM_OPT_CAMBOZOLA", value=>"yes" } ], + type => $types{rel_path}, + category => "images", + }, + { + name => "ZM_RELOAD_CAMBOZOLA", + default => "0", + description => "After how many seconds should Cambozola be reloaded in live view", + help => "Cambozola allows for the viewing of streaming MJPEG however it caches the entire stream into cache space on the computer, setting this to a number > 0 will cause it to automatically reload after that many seconds to avoid filling up a hard drive.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_TIMESTAMP_ON_CAPTURE", + default => "yes", + description => "Timestamp images as soon as they are captured", + help => "ZoneMinder can add a timestamp to images in two ways. The default method, when this option is set, is that each image is timestamped immediately when captured and so the image held in memory is marked right away. The second method does not timestamp the images until they are either saved as part of an event or accessed over the web. The timestamp used in both methods will contain the same time as this is preserved along with the image. The first method ensures that an image is timestamped regardless of any other circumstances but will result in all images being timestamped even those never saved or viewed. The second method necessitates that saved images are copied before being saved otherwise two timestamps perhaps at different scales may be applied. This has the (perhaps) desirable side effect that the timestamp is always applied at the same resolution so an image that has scaling applied will still have a legible and correctly scaled timestamp.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CPU_EXTENSIONS", + default => "yes", + description => "Use advanced CPU extensions to increase performance", + help => "When advanced processor extensions such as SSE2 or SSSE3 are available, ZoneMinder can use them, which should increase performance and reduce system load. Enabling this option on processors that do not support the advanced processors extensions used by ZoneMinder is harmless and will have no effect.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_FAST_IMAGE_BLENDS", + default => "yes", + description => "Use a fast algorithm to blend the reference image", + help => "To detect alarms ZoneMinder needs to blend the captured image with the stored reference image to update it for comparison with the next image. The reference blend percentage specified for the monitor controls how much the new image affects the reference image. There are two methods that are available for this. If this option is set then fast calculation which does not use any multiplication or division is used. This calculation is extremely fast, however it limits the possible blend percentages to 50%, 25%, 12.5%, 6.25%, 3.25% and 1.5%. Any other blend percentage will be rounded to the nearest possible one. The alternative is to switch this option off and use standard blending instead, which is slower.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_ADAPTIVE_SKIP", + default => "yes", + description => "Should frame analysis try and be efficient in skipping frames", + help => "In previous versions of ZoneMinder the analysis daemon would attempt to keep up with the capture daemon by processing the last captured frame on each pass. This would sometimes have the undesirable side-effect of missing a chunk of the initial activity that caused the alarm because the pre-alarm frames would all have to be written to disk and the database before processing the next frame, leading to some delay between the first and second event frames. Setting this option enables a newer adaptive algorithm where the analysis daemon attempts to process as many captured frames as possible, only skipping frames when in danger of the capture daemon overwriting yet to be processed frames. This skip is variable depending on the size of the ring buffer and the amount of space left in it. Enabling this option will give you much better coverage of the beginning of alarms whilst biasing out any skipped frames towards the middle or end of the event. However you should be aware that this will have the effect of making the analysis daemon run somewhat behind the capture daemon during events and for particularly fast rates of capture it is possible for the adaptive algorithm to be overwhelmed and not have time to react to a rapid build up of pending frames and thus for a buffer overrun condition to occur.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_BLEND_ALARMED_IMAGES", + default => "yes", + description => "Blend alarmed images to update the reference image", + help => "To detect alarms ZoneMinder compares an image with a reference image which is formed from a composite of the previous images. This option determines whether images that cause events are included in this process. Doing so may increase the precision of the alarmed region but can cause problems if wholescale lighting changes cause alarms as this would not get fed back into the image and an alarm may persist indefinately. A better way to achive the same effect in most cases is to lower substantially the reference blend percentage in specific monitors.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_MAX_SUSPEND_TIME", + default => "30", + description => "Maximum time that a monitor may have motion detection suspended", + help => "ZoneMinder allows monitors to have motion detection to be suspended, for instance while panning a camera. Ordinarily this relies on the operator resuming motion detection afterwards as failure to do so can leave a monitor in a permanently suspended state. This setting allows you to set a maximum time which a camera may be suspended for before it automatically resumes motion detection. This time can be extended by subsequent suspend indications after the first so continuous camera movement will also occur while the monitor is suspended.", + type => $types{integer}, + category => "config", + }, + # Deprecated, really no longer necessary + { + name => "ZM_OPT_REMOTE_CAMERAS", + default => "no", + description => "Are you going to use remote/networked cameras", + help => "ZoneMinder can work with both local cameras, ie. those attached physically to your computer and remote or network cameras. If you will be using networked cameras select this option.", + type => $types{boolean}, + category => "hidden", + }, + # Deprecated, now set on a per monitor basis using the Method field + { + name => "ZM_NETCAM_REGEXPS", + default => "yes", + description => "Use regular expression matching with network cameras", + help => "Traditionally ZoneMinder has used complex regular regular expressions to handle the multitude of formats that network cameras produce. In versions from 1.21.1 the default is to use a simpler and faster built in pattern matching methodology. This works well with most networks cameras but if you have problems you can try the older, but more flexible, regular expression based method by selecting this option. Note, to use this method you must have libpcre installed on your system.", + requires => [ { name => "ZM_OPT_REMOTE_CAMERAS", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_HTTP_VERSION", + default => "1.1", + description => "The version of HTTP that ZoneMinder will use to connect", + help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.", + type => { db_type=>"string", hint=>"1.1|1.0", pattern=>qr|^(1\.[01])$|, format=>q( $1?$1:"" ) }, + category => "network", + }, + { + name => "ZM_HTTP_UA", + default => "ZoneMinder", + description => "The user agent that ZoneMinder uses to identify itself", + help => "When ZoneMinder communicates with remote cameras it will identify itself using this string and it's version number. This is normally sufficient, however if a particular cameras expects only to communicate with certain browsers then this can be changed to a different string identifying ZoneMinder as Internet Explorer or Netscape etc.", + type => $types{string}, + category => "network", + }, + { + name => "ZM_HTTP_TIMEOUT", + default => "2500", + description => "How long ZoneMinder waits before giving up on images (milliseconds)", + help => "When retrieving remote images ZoneMinder will wait for this length of time before deciding that an image is not going to arrive and taking steps to retry. This timeout is in milliseconds (1000 per second) and will apply to each part of an image if it is not sent in one whole chunk.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MIN_RTP_PORT", + default => "40200", + description => "Minimum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the minimum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MAX_RTP_PORT", + default => "40499", + description => "Maximum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the maximum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting. You should also ensure that you have opened up at least two ports for each monitor that will be connecting to unicasting network cameras.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_OPT_FFMPEG", + default => "@OPT_FFMPEG@", + description => "Is the ffmpeg video encoder/decoder installed", + help => "ZoneMinder can optionally encode a series of video images into an MPEG encoded movie file for viewing, downloading or storage. This option allows you to specify whether you have the ffmpeg tools installed. Note that creating MPEG files can be fairly CPU and disk intensive and is not a required option as events can still be reviewed as video streams without it.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_FFMPEG", + default => "@PATH_FFMPEG@", + description => "Path to (optional) ffmpeg mpeg encoder", + help => "This path should point to where ffmpeg has been installed.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{abs_path}, + category => "images", + }, + { + name => "ZM_FFMPEG_INPUT_OPTIONS", + default => "", + description => "Additional input options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before the -i option). Check the ffmpeg documentation for a full list of options which may be used here.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_OUTPUT_OPTIONS", + default => "-r 25", + description => "Additional output options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after the -i option). Check the ffmpeg documentation for a full list of options which may be used here. The most common one will often be to force an output frame rate supported by the video encoder.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_FORMATS", + default => "mpg mpeg wmv asf avi* mov swf 3gp**", + description => "Formats to allow for ffmpeg video generation", + help => "Ffmpeg can generate video in many different formats. This option allows you to list the ones you want to be able to select. As new formats are supported by ffmpeg you can add them here and be able to use them immediately. Adding a '*' after a format indicates that this will be the default format used for web video, adding '**' defines the default format for phone video.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_LOG_LEVEL_SYSLOG", + default => "0", + description => "Save logging output to the system log", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_FILE", + default => "-5", + description => "Save logging output to component files", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_WEBLOG", + default => "-5", + description => "Save logging output to the weblog", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_DATABASE", + default => "0", + description => "Save logging output to the database", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DATABASE_LIMIT", + default => "7 day", + description => "Maximum number of log entries to retain", + help => "If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as ' day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.", + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG", + default => "no", + description => "Switch debugging on", + help => "ZoneMinder components usually support debug logging available to help with diagnosing problems. Binary components have several levels of debug whereas more other components have only one. Normally this is disabled to minimise performance penalties and avoid filling logs too quickly. This option lets you switch on other options that allow you to configure additional debug information to be output. Components will pick up this instruction when they are restarted.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_TARGET", + default => "", + description => "What components should have extra debug enabled", + help => "There are three scopes of debug available. Leaving this option blank means that all components will use extra debug (not recommended). Setting this option to '_', e.g. _zmc, will limit extra debug to that component only. Setting this option to '__', e.g. '_zmc_m1' will limit extra debug to that instance of the component only. This is ordinarily what you probably want to do. To debug scripts use their names without the .pl extension, e.g. '_zmvideo' and to debug issues with the web interface use '_web'. You can specify multiple targets by separating them with '|' characters.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_LEVEL", + default => 1, + description => "What level of extra debug should be enabled", + help => "There are 9 levels of debug available, with higher numbers being more debug and level 0 being no debug. However not all levels are used by all components. Also if there is debug at a high level it is usually likely to be output at such a volume that it may obstruct normal operation. For this reason you should set the level carefully and cautiously until the degree of debug you wish to see is present. Scripts and the web interface only have one level so this is an on/off type option for them.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => { db_type=>"integer", hint=>"1|2|3|4|5|6|7|8|9", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_FILE", + default => "@ZM_TMPDIR@/zm_debug.log+", + description => "Where extra debug is output to", + help => "This option allows you to specify a different target for debug output. All components have a default log file which will norally be in /tmp or /var/log and this is where debug will be written to if this value is empty. Adding a path here will temporarily redirect debug, and other logging output, to this file. This option is a simple filename and you are debugging several components then they will all try and write to the same file with undesirable consequences. Appending a '+' to the filename will cause the file to be created with a '.' suffix containing your process id. In this way debug from each run of a component is kept separate. This is the recommended setting as it will also prevent subsequent runs from overwriting the same log. You should ensure that permissions are set up to allow writing to the file and directory specified here.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_CHECK_PERIOD", + default => "900", + description => "Time period used when calculating overall system health", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to indicate what period of historical events are used in this calculation. This value is expressed in seconds and is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_WAR_COUNT", + default => "1", + description => "Number of warnings indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alert state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_ERR_COUNT", + default => "1", + description => "Number of errors indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alert state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_FAT_COUNT", + default => "0", + description => "Number of fatal error indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alert state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_WAR_COUNT", + default => "100", + description => "Number of warnings indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alarm state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_ERR_COUNT", + default => "10", + description => "Number of errors indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alarm state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_FAT_COUNT", + default => "1", + description => "Number of fatal error indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alarm state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_RECORD_EVENT_STATS", + default => "yes", + description => "Record event statistical information, switch off if too slow", + help => "This version of ZoneMinder records detailed information about events in the Stats table. This can help in profiling what the optimum settings are for Zones though this is tricky at present. However in future releases this will be done more easily and intuitively, especially with a large sample of events. The default option of 'yes' allows this information to be collected now in readiness for this but if you are concerned about performance you can switch this off in which case no Stats information will be saved.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_RECORD_DIAG_IMAGES", + default => "no", + description => "Record intermediate alarm diagnostic images, can be very slow", + help => "In addition to recording event statistics you can also record the intermediate diagnostic images that display the results of the various checks and processing that occur when trying to determine if an alarm event has taken place. There are several of these images generated for each frame and zone for each alarm or alert frame so this can have a massive impact on performance. Only switch this setting on for debug or analysis purposes and remember to switch it off again once no longer required.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_DUMP_CORES", + default => "no", + description => "Create core files on unexpected process failure.", + help => "When an unrecoverable error occurs in a ZoneMinder binary process is has traditionally been trapped and the details written to logs to aid in remote analysis. However in some cases it is easier to diagnose the error if a core file, which is a memory dump of the process at the time of the error, is created. This can be interactively analysed in the debugger and may reveal more or better information than that available from the logs. This option is recommended for advanced users only otherwise leave at the default. Note using this option to trigger core files will mean that there will be no indication in the binary logs that a process has died, they will just stop, however the zmdc log will still contain an entry. Also note that you may have to explicitly enable core file creation on your system via the 'ulimit -c' command or other means otherwise no file will be created regardless of the value of this option.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_PATH_MAP", + default => "/dev/shm", + description => "Path to the mapped memory files that that ZoneMinder can use", + help => "ZoneMinder has historically used IPC shared memory for shared data between processes. This has it's advantages and limitations. This version of ZoneMinder can use an alternate method, mapped memory, instead with can be enabled with the --enable--mmap directive to configure. This requires less system configuration and is generally more flexible. However it requires each shared data segment to map onto a filesystem file. This option indicates where those mapped files go. You should ensure that this location has sufficient space for these files and for the best performance it should be a tmpfs file system or ramdisk otherwise disk access may render this method slower than the regular shared memory one.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SOCKS", + default => "@ZM_TMPDIR@", + description => "Path to the various Unix domain socket files that ZoneMinder uses", + help => "ZoneMinder generally uses Unix domain sockets where possible. This reduces the need for port assignments and prevents external applications from possibly compromising the daemons. However each Unix socket requires a .sock file to be created. This option indicates where those socket files go.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_LOGS", + default => "@ZM_LOGDIR@", + description => "Path to the various logs that the ZoneMinder daemons generate", + help => "There are various daemons that are used by ZoneMinder to perform various tasks. Most generate helpful log files and this is where they go. They can be deleted if not required for debugging.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SWAP", + default => "@ZM_TMPDIR@", + description => "Path to location for temporary swap images used in streaming", + help => "Buffered playback requires temporary swap images to be stored for each instance of the streaming daemons. This option determines where these images will be stored. The images will actually be stored in sub directories beneath this location and will be automatically cleaned up after a period of time.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_WEB_TITLE_PREFIX", + default => "ZM", + description => "The title prefix displayed on each window", + help => "If you have more than one installation of ZoneMinder it can be helpful to display different titles for each one. Changing this option allows you to customise the window titles to include further information to aid identification.", + type => $types{string}, + category => "web", + }, + { + name => "ZM_WEB_RESIZE_CONSOLE", + default => "yes", + description => "Should the console window resize itself to fit", + help => "Traditionally the main ZoneMinder web console window has resized itself to shrink to a size small enough to list only the monitors that are actually present. This is intended to make the window more unobtrusize but may not be to everyones tastes, especially if opened in a tab in browsers which support this kind if layout. Switch this option off to have the console window size left to the users preference", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_POPUP_ON_ALARM", + default => "yes", + description => "Should the monitor window jump to the top if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to pop to the front if an alarm occurs when the window is minimised or behind another window. This is most useful if your monitors are over doors for example when they can pop up if someone comes to the doorway.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_X10", + default => "no", + description => "Support interfacing with X10 devices", + help => "If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.", + type => $types{boolean}, + category => "x10", + }, + { + name => "ZM_X10_DEVICE", + default => "/dev/ttyS0", + description => "What device is your X10 controller connected on", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.", + type => $types{abs_path}, + category => "x10", + }, + { + name => "ZM_X10_HOUSE_CODE", + default => "A", + description => "What X10 house code should be used", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.", + type => { db_type=>"string", hint=>"A-P", pattern=>qr|^([A-P])|i, format=>q( uc($1) ) }, + category => "x10", + }, + { + name => "ZM_X10_DB_RELOAD_INTERVAL", + default => "60", + description => "How often (in seconds) the X10 daemon reloads the monitors from the database", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "The zmx10 daemon periodically checks the database to find out what X10 events trigger, or result from, alarms. This option determines how frequently this check occurs, unless you change this area frequently this can be a fairly large value.", + type => $types{integer}, + category => "x10", + }, + { + name => "ZM_WEB_SOUND_ON_ALARM", + default => "no", + description => "Should the monitor window play a sound if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to play a sound to alert you if an alarm occurs.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_ALARM_SOUND", + default => "", + description => "The sound to play on alarm, put this in the sounds directory", + help => "You can specify a sound file to play if an alarm occurs whilst you are watching a live monitor stream. So long as your browser understands the format it does not need to be any particular type. This file should be placed in the sounds directory defined earlier.", + type => $types{file}, + requires => [ { name => "ZM_WEB_SOUND_ON_ALARM", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_COMPACT_MONTAGE", + default => "no", + description => "Compact the montage view by removing extra detail", + help => "The montage view shows the output of all of your active monitors in one window. This include a small menu and status information for each one. This can increase the web traffic and make the window larger than may be desired. Setting this option on removes all this extraneous information and just displays the images.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_FAST_DELETE", + default => "yes", + description => "Delete only event database records for speed", + help => "Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if your are trying to do a lot of events at once. It is recommended that you set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_STRICT_VIDEO_CONFIG", + default => "yes", + description => "Allow errors in setting video config to be fatal", + help => "With some video devices errors can be reported in setting the various video attributes when in fact the operation was successful. Switching this option off will still allow these errors to be reported but will not cause them to kill the video capture daemon. Note however that doing this will cause all errors to be ignored including those which are genuine and which may cause the video capture to not function correctly. Use this option with caution.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_SIGNAL_CHECK_POINTS", + default => "10", + description => "How many points in a captured image to check for signal loss", + help => "For locally attached video cameras ZoneMinder can check for signal loss by looking at a number of random points on each captured image. If all of these points are set to the same fixed colour then the camera is assumed to have lost signal. When this happens any open events are closed and a short one frame signal loss event is generated, as is another when the signal returns. This option defines how many points on each image to check. Note that this is a maximum, any points found to not have the check colour will abort any further checks so in most cases on a couple of points will actually be checked. Network and file based cameras are never checked.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_V4L_MULTI_BUFFER", + default => "yes", + description => "Use more than one buffer for Video 4 Linux devices", + help => "Performance when using Video 4 Linux devices is usually best if multiple buffers are used allowing the next image to be captured while the previous one is being processed. If you have multiple devices on a card sharing one input that requires switching then this approach can sometimes cause frames from one source to be mixed up with frames from another. Switching this option off prevents multi buffering resulting in slower but more stable image capture. This option is ignored for non-local cameras or if only one input is present on a capture chip. This option addresses a similar problem to the ZM_CAPTURES_PER_FRAME option and you should normally change the value of only one of the options at a time.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CAPTURES_PER_FRAME", + default => "1", + description => "How many images are captured per returned frame, for shared local cameras", + help => "If you are using cameras attached to a video capture card which forces multiple inputs to share one capture chip, it can sometimes produce images with interlaced frames reversed resulting in poor image quality and a distinctive comb edge appearance. Increasing this setting allows you to force additional image captures before one is selected as the captured frame. This allows the capture hardware to 'settle down' and produce better quality images at the price of lesser capture rates. This option has no effect on (a) network cameras, or (b) where multiple inputs do not share a capture chip. This option addresses a similar problem to the ZM_V4L_MULTI_BUFFER option and you should normally change the value of only one of the options at a time.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_FILTER_RELOAD_DELAY", + default => "300", + description => "How often (in seconds) filters are reloaded in zmfilter", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are reloaded from the database to get the latest versions or new filters. If you don't change filters very often this value can be set to a large value.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FILTER_EXECUTE_INTERVAL", + default => "60", + description => "How often (in seconds) to run automatic saved filters", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are executed on the saved event in the database. If you want a rapid response to new events this should be a smaller value, however this may increase the overall load on the system and affect performance of other elements.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_UPLOAD", + default => "no", + description => "Should ZoneMinder support uploading events from filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should be uploaded to a remote server for archiving. This option specifies whether this functionality should be available", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_FORMAT", + default => "tar", + description => "What format the uploaded events should be created in.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "Uploaded events may be stored in either .tar or .zip format, this option specifies which. Note that to use this you will need to have the Archive::Tar and/or Archive::Zip perl modules installed.", + type => { db_type=>"string", hint=>"tar|zip", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^t/ ? "tar" : "zip" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_COMPRESS", + default => "no", + description => "Should archive files be compressed", + help => "When the archive files are created they can be compressed. However in general since the images are compressed already this saves only a minimal amount of space versus utilising more CPU in their creation. Only enable if you have CPU to waste and are limited in disk space on your remote server or bandwidth.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_ANALYSE", + default => "no", + description => "Include the analysis files in the archive", + help => "When the archive files are created they can contain either just the captured frames or both the captured frames and, for frames that caused an alarm, the analysed image with the changed area highlighted. This option controls files are included. Only include analysed frames if you have a high bandwidth connection to the remote server or if you need help in figuring out what caused an alarm in the first place as archives with these files in can be considerably larger.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PROTOCOL", + default => "ftp", + description => "What protocol to use to upload events", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "ZoneMinder can upload events to a remote server using either FTP or SFTP. Regular FTP is widely supported but not necessarily very secure whereas SFTP (Secure FTP) runs over an ssh connection and so is encrypted and uses regular ssh ports. Note that to use this you will need to have the appropriate perl module, either Net::FTP or Net::SFTP installed depending on your choice.", + type => { db_type=>"string", hint=>"ftp|sftp", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^f/ ? "ftp" : "sftp" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_HOST", + default => "", + description => "The remote server to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_HOST", + default => "", + description => "The remote server to upload events to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PORT", + default => "", + description => "The port on the remote upload server, if not the default (SFTP only)", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are using the SFTP protocol then this option allows you to specify a particular port to use for connection. If this option is left blank then the default, port 22, is used. This option is ignored for FTP uploads.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_USER", + default => "", + description => "Your ftp username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the username that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_USER", + default => "", + description => "Remote server username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASS", + default => "", + description => "Your ftp password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the password that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_PASS", + default => "", + description => "Remote server password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_LOC_DIR", + default => "@ZM_TMPDIR@", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_LOC_DIR", + default => "@ZM_TMPDIR@", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the maximum ftp inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the maximum inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASSIVE", + default => "yes", + description => "Use passive ftp when uploading", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates that ftp transfers should be done in passive mode. This uses a single connection for all ftp activity and, whilst slower than active transfers, is more robust and likely to work from behind filewalls. This option is ignored for SFTP transfers.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "If your computer is behind a firewall or proxy you may need to set FTP to passive mode. In fact for simple transfers it makes little sense to do otherwise anyway but you can set this to 'No' if you wish.", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_DEBUG", + default => "no", + description => "Switch ftp debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be included in the zmfilter log file.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_DEBUG", + default => "no", + description => "Switch upload debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be generated by the underlying transfer modules and included in the logs.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_OPT_EMAIL", + default => "no", + description => "Should ZoneMinder email you details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details emailed to you at a designated email address. This will allow you to be notified of events as soon as they occur and also to quickly view the events directly. This option specifies whether this functionality should be available. The email created with this option can be any size and is intended to be sent to a regular email reader rather than a mobile device.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_EMAIL_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)" +body = " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder"', + description => "The text of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_EMAIL_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)", + description => "The subject of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the subject of the email that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_EMAIL_BODY", + default => " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder", + description => "The body of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_OPT_MESSAGE", + default => "no", + description => "Should ZoneMinder message you with details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details sent to you at a designated short message email address. This will allow you to be notified of events as soon as they occur. This option specifies whether this functionality should be available. The email created by this option will be brief and is intended to be sent to an SMS gateway or a minimal mail reader such as a mobile device or phone rather than a regular email reader.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_MESSAGE_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the short message email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_MESSAGE_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI%" +body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score."', + description => "The text of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_MESSAGE_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI%", + description => "The subject of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the subject of the message that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_MESSAGE_BODY", + default => "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.", + description => "The body of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_NEW_MAIL_MODULES", + default => "no", + description => "Use a newer perl method to send emails", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "Traditionally ZoneMinder has used the MIME::Entity perl module to construct and send notification emails and messages. Some people have reported problems with this module not being present at all or flexible enough for their needs. If you are one of those people this option allows you to select a new mailing method using MIME::Lite and Net::SMTP instead. This method was contributed by Ross Melin and should work for everyone but has not been extensively tested so currently is not selected by default.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_HOST", + default => "localhost", + description => "The host address of your SMTP mail server", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "If you have chosen SMTP as the method by which to send notification emails or messages then this option allows you to choose which SMTP server to use to send them. The default of localhost may work if you have the sendmail, exim or a similar daemon running however you may wish to enter your ISP's SMTP mail server here.", + type => $types{hostname}, + category => "mail", + }, + { + name => "ZM_FROM_EMAIL", + default => "", + description => "The email address you wish your event notifications to originate from", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can appear to come from a designated email address to help you with mail filtering etc. An address of something like ZoneMinder\@your.domain is recommended.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_URL", + default => "", + description => "The URL of your ZoneMinder installation", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. http://host.your.domain/zm.php.", + type => $types{url}, + category => "mail", + }, + { + name => "ZM_MAX_RESTART_DELAY", + default => "600", + description => "Maximum delay (in seconds) for daemon restart attempts.", + help => "The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_CHECK_INTERVAL", + default => "10", + description => "How often to check the capture daemons have not locked up", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_MAX_DELAY", + default => "5", + description => "The maximum delay allowed since the last captured image", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.", + type => $types{decimal}, + category => "system", + }, + { + + name => "ZM_RUN_AUDIT", + default => "yes", + description => "Run zmaudit to check data consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.", + type => $types{boolean}, + category => "system", + }, + { + + name => "ZM_AUDIT_CHECK_INTERVAL", + default => "900", + description => "How often to check database and filesystem consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FORCED_ALARM_SCORE", + default => "255", + description => "Score to give forced alarms", + help => "The 'zmu' utility can be used to force an alarm on a monitor rather than rely on the motion detection algorithms. This option determines what score to give these alarms to distinguish them from regular ones. It must be 255 or less.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_BULK_FRAME_INTERVAL", + default => "100", + description => "How often a bulk frame should be written to the database", + help => "Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation ('Record' or 'Mocord' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one 'bulk' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_EVENT_CLOSE_MODE", + default => "idle", + description => "When continuous events are closed.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.", + type => $types{boolean}, + type => { db_type=>"string", hint=>"time|idle|alarm", pattern=>qr|^([tia])|i, format=>q( ($1 =~ /^t/) ? "time" : ($1 =~ /^i/ ? "idle" : "time" ) ) }, + category => "config", + }, + # Deprecated, superseded by event close mode + { + name => "ZM_FORCE_CLOSE_EVENTS", + default => "no", + description => "Close events at section ends.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section and ordinarily this will prevent the event being closed until the motion has ceased. Switching this option on will force the event closed at the specified time regardless of any motion activity.", + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_CREATE_ANALYSIS_IMAGES", + default => "yes", + description => "Create analysed alarm images with motion outlined", + help => "By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_WEIGHTED_ALARM_CENTRES", + default => "no", + description => "Use a weighted algorithm to calculate the centre of an alarm", + help => "ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_EVENT_IMAGE_DIGITS", + default => "3", + description => "How many significant digits are used in event image numbering", + help => "As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_DEFAULT_ASPECT_RATIO", + default => "4:3", + description => "The default width:height aspect ratio used in monitors", + help => "When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format : and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.", + type => $types{string}, + category => "config", + }, + { + name => "ZM_USER_SELF_EDIT", + default => "no", + description => "Allow unprivileged users to change their details", + help => "Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_FRAME_SERVER", + default => "no", + description => "Should analysis farm out the writing of images to disk", + #requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ], + help => "In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_FRAME_SOCKET_SIZE", + default => "0", + description => "Specify the frame server socket buffer size if non-standard", + requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ], + help => "For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_CONTROL", + default => "no", + description => "Support controllable (e.g. PTZ) cameras", + help => "ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_OPT_TRIGGERS", + default => "no", + description => "Interface external event triggers via socket or device files", + help => "ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_CHECK_FOR_UPDATES", + default => "yes", + description => "Check with zoneminder.com for updated versions", + help => "From ZoneMinder version 1.17.0 onwards new versions are expected to be more frequent. To save checking manually for each new version ZoneMinder can check with the zoneminder.com website to determine the most recent release. These checks are infrequent, about once per week, and no personal or system information is transmitted other than your current version number. If you do not wish these checks to take place or your ZoneMinder system has no internet access you can switch these check off with this configuration variable", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_UPDATE_CHECK_PROXY", + default => "", + description => "Proxy url if required to access zoneminder.com", + help => "If you use a proxy to access the internet then ZoneMinder needs to know so it can access zoneminder.com to check for updates. If you do use a proxy enter the full proxy url here in the form of http://:/", + type => $types{string}, + category => "system", + }, + { + name => "ZM_SHM_KEY", + default => "0x7a6d0000", + description => "Shared memory root key to use", + help => "ZoneMinder uses shared memory to speed up communication between modules. To identify the right area to use shared memory keys are used. This option controls what the base key is, each monitor will have it's Id or'ed with this to get the actual key used. You will not normally need to change this value unless it clashes with another instance of ZoneMinder on the same machine. Only the first four hex digits are used, the lower four will be masked out and ignored.", + type => $types{hexadecimal}, + category => "system", + }, + # Deprecated, really no longer necessary + { + name => "ZM_WEB_REFRESH_METHOD", + default => "javascript", + description => "What method windows should use to refresh themselves", + help => "Many windows in Javascript need to refresh themselves to keep their information current. This option determines what method they should use to do this. Choosing 'javascript' means that each window will have a short JavaScript statement in with a timer to prompt the refresh. This is the most compatible method. Choosing 'http' means the refresh instruction is put in the HTTP header. This is a cleaner method but refreshes are interrupted or cancelled when a link in the window is clicked meaning that the window will no longer refresh and this would have to be done manually.", + type => { db_type=>"string", hint=>"javascript|http", pattern=>qr|^([jh])|i, format=>q( $1 =~ /^j/ ? "javascript" : "http" ) }, + category => "hidden", + }, + { + name => "ZM_WEB_EVENT_SORT_FIELD", + default => "DateTime", + description => "Default field the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what field is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"Id|Name|Cause|MonitorName|DateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore", pattern=>qr|.|, format=>q( $1 ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENT_SORT_ORDER", + default => "asc", + description => "Default order the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what order (ascending or descending) is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"asc|desc", pattern=>qr|^([ad])|i, format=>q( $1 =~ /^a/i ? "asc" : "desc" ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENTS_PER_PAGE", + default => "25", + description => "How many events to list per page in paged mode", + help => "In the event list view you can either list all events or just a page at a time. This option controls how many events are listed per page in paged mode and how often to repeat the column headers in non-paged mode.", + type => $types{integer}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMBS", + default => "no", + description => "Display mini-thumbnails of event images in event lists", + help => "Ordinarily the event lists just display text details of the events to save space and time. By switching this option on you can also display small thumbnails to help you identify events of interest. The size of these thumbnails is controlled by the following two options.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_WIDTH", + default => "48", + description => "The width of the thumbnails that appear in the event lists", + help => "This options controls the width of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a height instead in the next option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_HEIGHT", + default => "0", + description => "The height of the thumbnails that appear in the event lists", + help => "This options controls the height of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a width instead in the previous option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_USE_OBJECT_TAGS", + default => "yes", + description => "Wrap embed in object tags for media content", + help => "There are two methods of including media content in web pages. The most common way is use the EMBED tag which is able to give some indication of the type of content. However this is not a standard part of HTML. The official method is to use OBJECT tags which are able to give more information allowing the correct media viewers etc to be loaded. However these are less widely supported and content may be specifically tailored to a particular platform or player. This option controls whether media content is enclosed in EMBED tags only or whether, where appropriate, it is additionally wrapped in OBJECT tags. Currently OBJECT tags are only used in a limited number of circumstances but they may become more widespread in the future. It is suggested that you leave this option on unless you encounter problems playing some content.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_H_REFRESH_MAIN", + default => "300", + introduction => "There are now a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client.\n\nThe next few options control what happens when the client is running in 'high' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a local network or high speed link. In most cases the default values will be suitable as a starting point.", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_CYCLE", + default => "10", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_IMAGE", + default => "5", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_STATUS", + default => "3", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_EVENTS", + default => "30", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "highband", + }, + { + name => "ZM_WEB_H_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_BITRATE", + default => "150000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_MAXFPS", + default => "15", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_SCALE_THUMBS", + default => "no", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_AJAX_TIMEOUT", + default => "3000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_M_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + introduction => "The next few options control what happens when the client is running in 'medium' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a slower cable or DSL link. In most cases the default values will be suitable as a starting point.", + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_CYCLE", + default => "20", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_IMAGE", + default => "10", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_STATUS", + default => "5", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_EVENTS", + default => "60", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "medband", + }, + { + name => "ZM_WEB_M_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_BITRATE", + default => "75000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_MAXFPS", + default => "10", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_AJAX_TIMEOUT", + default => "5000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_L_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + introduction => "The next few options control what happens when the client is running in 'low' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a modem or slow link. In most cases the default values will be suitable as a starting point.", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_CYCLE", + default => "30", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_IMAGE", + default => "15", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_STATUS", + default => "10", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_EVENTS", + default => "180", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "lowband", + }, + { + name => "ZM_WEB_L_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_BITRATE", + default => "25000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_SHOW_PROGRESS", + default => "no", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_P_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_BITRATE", + default => "8000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_DYN_LAST_VERSION", + default => "", + description => "What the last version of ZoneMinder recorded from zoneminder.com is", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_CURR_VERSION", + default => "@VERSION@", + description => "What the effective current version of ZoneMinder is, might be different from actual if versions ignored", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DB_VERSION", + default => "@VERSION@", + description => "What the version of the database is, from zmupdate", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_LAST_CHECK", + default => "", + description => "When the last check for version from zoneminder.com was", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_NEXT_REMINDER", + default => "", + description => "When the earliest time to remind about versions will be", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DONATE_REMINDER_TIME", + default => 0, + description => "When the earliest time to remind about donations will be", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_SHOW_DONATE_REMINDER", + default => "yes", + description => "Remind about donations or not", + help => "", + type => $types{boolean}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_EYEZM_DEBUG", + default => "no", + description => "Switch additional debugging on for eyeZm Plugin", + help => "Enable or Disable extra debugging from the eyeZm Plugin. Extra debugging information will be displayed in it's own file (EYEZM_LOG_TO_FILE is set), or your Apache error log", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_TO_FILE", + default => "yes", + description => "When eyeZm Debugging is enabled, enabling this logs output to it's own file", + help => "When EYEZM_DEBUG is on and EYEZM_LOG_TO_FILE is on, output generated from the eyeZm Plugin will go to it's own file. Otherwise it will go to the apache error log.", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_FILE", + default => "@ZM_LOGDIR@/zm_xml.log", + description => "Default filename to use when logging eyeZm Output and EYEZM_LOG_TO_FILE is enabled", + help => "This file will contain it's own output from the eyeZm Plugin when EYEZM_LOG_TO_FILE and EYEZM_DEBUG are both enabled", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_EVENT_VCODEC", + default => "mpeg4", + description => "Default video-codec to use for encoding events", + help => "The eyeZm Plugin calls FFMPEG externally to encode the captured images. If your FFMPEG is not built with support for H264, change this to MPEG-4. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+).", + type => { db_type=>"string", hint=>"mpeg4|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mpeg4" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_FEED_VCODEC", + default => "mjpeg", + description => "Default video-codec to use for streaming the live feed", + help => "Determines whether the live stream is generated using native MJPEG streaming with ZoneMinder, or H264 using FFMPEG and HTML-5 streaming. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+). This is just a default parameter, and can be overridden with eyeZm.", + type => { db_type=>"string", hint=>"mjpeg|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mjpeg" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_BR", + default => "96k", + description => "Default bit-rate to use with FFMPEG for H264 streaming", + help => "When using the eyeZm Plugin to stream H264 data, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_EVBR", + default => "128k", + description => "Default bit-rate to use with FFMPEG for H264 event viewing", + help => "When using the eyeZm Plugin to view events in H264, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_TIMEOUT", + default => "20", + description => "Timeout (sec) to wait for H264 stream to start before terminating", + help => "The eyeZm Plugin will attempt to spawn an H264 stream when requested, and require that it complete within the timeout specified. If you have a slow system or find through the logs that the H264 stream is not starting because the timeout is expiring, even though FFMPEG is running, try increasing this value. If you have a fast system, decreasing this value can improve the responsiveness when there are issues starting H264 streams", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_SEG_DURATION", + default => "3", + description => "Segment duration used for streaming using HTTP-5 Streaming protocol", + help => "The HTTP-5 Live Streaming Protocol segments the input video stream into small chunks of a duration specified by this parameter. Increasing the segment duration will help with choppy connections on the other end, but will increase the latency in starting a stream.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_PATH_PLUGINS", + default => "/usr/share/zm", + description => "Path to the plugin folder", + help => "3d-party plugins have to be placed here.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PLUGIN_EXTENSION", + default => ".zmpl", + description => "Default extension of plugins to found.", + help => "Default extension of plugins to found.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_PLUGINS_CONFIG_PATH", + default => "/usr/share/zm/plugins.conf", + description => "Path to the config file for plugins.", + help => "Path to the config file for plugins.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_LOAD_PLUGINS", + default => "no", + description => "Load and use 3d-party plugins", + help => "3d-party plugins will be loaded and used for analysing.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_TURNOFF_NATIVE_ANALYSIS", + default => "no", + description => "Turn native ZM\'s image analysis possibility off", + help => "Image analysis with ZM\'s motion detected function will be turned off. Only detection functions from loaded plugins will be used. Note, that if no plugins have be loaded, no detection will be done.", + type => $types{boolean}, + category => "config", + }, + +); + +our %options_hash = map { ( $_->{name}, $_ ) } @options; + +# This function should never need to be called explicitly, except if +# this module is 'require'd rather than 'use'd. See zmconfgen.pl. +sub initialiseConfig +{ + return if ( $configInitialised ); + + # Do some initial data munging to finish the data structures + # Create option ids + my $option_id = 0; + foreach my $option ( @options ) + { + if ( defined($option->{default}) ) + { + $option->{value} = $option->{default} + } + else + { + $option->{value} = ''; + } + #next if ( $option->{category} eq 'hidden' ); + $option->{id} = $option_id++; + } + $configInitialised = 1; +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigData - ZoneMinder Configuration Data module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigData; + use ZoneMinder::ConfigData qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigData module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in.orig b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in.orig new file mode 100644 index 000000000..55c0ec302 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in.orig @@ -0,0 +1,2015 @@ +# ========================================================================== +# +# ZoneMinder Config Data Module, $Date: 2011-01-20 18:49:42 +0000 (Thu, 20 Jan 2011) $, $Revision: 3230 $ +# 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::ConfigData; + +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 = ( + 'data' => [ qw( + %types + @options + %options_hash + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'data'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Configuration Data +# +# ========================================================================== + +use Carp; + +our $configInitialised = 0; + +sub INIT +{ + initialiseConfig(); +} + +# Types +our %types = +( + string => { db_type=>"string", hint=>"string", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + alphanum => { db_type=>"string", hint=>"alphanumeric", pattern=>qr|^([a-zA-Z0-9-_]+)$|, format=>q( $1 ) }, + text => { db_type=>"text", hint=>"free text", pattern=>qr|^(.+)$|, format=>q( $1 ) }, + boolean => { db_type=>"boolean", hint=>"yes|no", pattern=>qr|^([yn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : "no" ) }, + integer => { db_type=>"integer", hint=>"integer", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + decimal => { db_type=>"decimal", hint=>"decimal", pattern=>qr|^(\d+(?:\.\d+)?)$|, format=>q( $1 ) }, + hexadecimal => { db_type=>"hexadecimal", hint=>"hexadecimal", pattern=>qr|^(?:0x)?([0-9a-f]{1,8})$|, format=>q( "0x".$1 ) }, + tristate => { db_type=>"string", hint=>"auto|yes|no", pattern=>qr|^([ayn])|i, check=>q( $1 ), format=>q( ($1 =~ /^y/) ? "yes" : ($1 =~ /^n/ ? "no" : "auto" ) ) }, + abs_path => { db_type=>"string", hint=>"/absolute/path/to/somewhere", pattern=>qr|^((?:/[^/]*)+?)/?$|, format=>q( $1 ) }, + rel_path => { db_type=>"string", hint=>"relative/path/to/somewhere", pattern=>qr|^((?:[^/].*)?)/?$|, format=>q( $1 ) }, + directory => { db_type=>"string", hint=>"directory", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + file => { db_type=>"string", hint=>"filename", pattern=>qr|^([a-zA-Z0-9-_.]+)$|, format=>q( $1 ) }, + hostname => { db_type=>"string", hint=>"host.your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)$|, format=>q( $1 ) }, + url => { db_type=>"string", hint=>"http://host.your.domain/", pattern=>qr|^(?:http://)?(.+)$|, format=>q( "http://".$1 ) }, + email => { db_type=>"string", hint=>"your.name\@your.domain", pattern=>qr|^([a-zA-Z0-9_.-]+)\@([a-zA-Z0-9_.-]+)$|, format=>q( $1\@$2 ) }, +); + +our @options = +( + { + name => "ZM_LANG_DEFAULT", + default => "en_gb", + description => "Default language used by web interface", + help => "ZoneMinder allows the web interface to use languages other than English if the appropriate language file has been created and is present. This option allows you to change the default language that is used from the shipped language, British English, to another language", + type => $types{string}, + category => "system", + }, + { + name => "ZM_OPT_USE_AUTH", + default => "no", + description => "Authenticate user logins to ZoneMinder", + help => "ZoneMinder can run in two modes. The simplest is an entirely unauthenticated mode where anyone can access ZoneMinder and perform all tasks. This is most suitable for installations where the web server access is limited in other ways. The other mode enables user accounts with varying sets of permissions. Users must login or authenticate to access ZoneMinder and are limited by their defined permissions.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_TYPE", + default => "builtin", + description => "What is used to authenticate ZoneMinder users", + help => "ZoneMinder can use two methods to authenticate users when running in authenticated mode. The first is a builtin method where ZoneMinder provides facilities for users to log in and maintains track of their identity. The second method allows interworking with other methods such as http basic authentication which passes an independently authentication 'remote' user via http. In this case ZoneMinder would use the supplied user without additional authentication provided such a user is configured ion ZoneMinder.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"builtin|remote", pattern=>qr|^([br])|i, format=>q( $1 =~ /^b/ ? "builtin" : "remote" ) }, + category => "system", + }, + { + name => "ZM_AUTH_RELAY", + default => "hashed", + description => "Method used to relay authentication information", + help => "When ZoneMinder is running in authenticated mode it can pass user details between the web pages and the back end processes. There are two methods for doing this. This first is to use a time limited hashed string which contains no direct username or password details, the second method is to pass the username and passwords around in plaintext. This method is not recommend except where you do not have the md5 libraries available on your system or you have a completely isolated system with no external access. You can also switch off authentication relaying if your system is isolated in other ways.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" } ], + type => { db_type=>"string", hint=>"hashed|plain|none", pattern=>qr|^([hpn])|i, format=>q( ($1 =~ /^h/) ? "hashed" : ($1 =~ /^p/ ? "plain" : "none" ) ) }, + category => "system", + }, + { + name => "ZM_AUTH_HASH_SECRET", + default => "...Change me to something unique...", + description => "Secret for encoding hashed authentication information", + help => "When ZoneMinder is running in hashed authenticated mode it is necessary to generate hashed strings containing encrypted sensitive information such as usernames and password. Although these string are reasonably secure the addition of a random secret increases security substantially.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{string}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_IPS", + default => "yes", + description => "Include IP addresses in the authentication hash", + help => "When ZoneMinder is running in hashed authenticated mode it can optionally include the requesting IP address in the resultant hash. This adds an extra level of security as only requests from that address may use that authentication key. However in some circumstances, such as access over mobile networks, the requesting address can change for each request which will cause most requests to fail. This option allows you to control whether IP addresses are included in the authentication hash on your system. If you experience intermitent problems with authentication, switching this option off may help.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_AUTH_HASH_LOGINS", + default => "no", + description => "Allow login by authentication hash", + help => "The normal process for logging into ZoneMinder is via the login screen with username and password. In some circumstances it may be desirable to allow access directly to one or more pages, for instance from a third party application. If this option is enabled then adding an 'auth' parameter to any request will include a shortcut login bypassing the login screen, if not already logged in. As authentication hashes are time and, optionally, IP limited this can allow short-term access to ZoneMinder screens from other web pages etc. In order to use this the calling application will hae to generate the authentication hash itself and ensure it is valid. If you use this option you should ensure that you have modified the ZM_AUTH_HASH_SECRET to somethign unique to your system.", + requires => [ { name=>"ZM_OPT_USE_AUTH", value=>"yes" }, { name=>"ZM_AUTH_RELAY", value=>"hashed" } ], + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_DIR_EVENTS", + default => "events", + description => "Directory where events are stored", + help => "This is the path to the events directory where all the event images and other miscellaneous files are stored. It is normally given as a subdirectory of the web directory you have specified earlier however if disk space is tight it can reside on another partition in which case you should create a link from that area to the path you give here.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_USE_DEEP_STORAGE", + default => "yes", + description => "Use a deep filesystem hierarchy for events", + help => "Traditionally ZoneMinder stores all events for a monitor in one directory for that monitor. This is simple and efficient except when you have very large amounts of events. Some filesystems are unable to store more than 32k files in one directory and even without this limitation, large numbers of files in a directory can slow creation and deletion of files. This option allows you to select an alternate method of storing events by year/month/day/hour/min/second which has the effect of separating events out into more directories, resulting in less per directory, and also making it easier to manually navigate to any events that may have happened at a particular time or date.", + type => $types{boolean}, + category => "paths", + }, + { + name => "ZM_DIR_IMAGES", + default => "images", + description => "Directory where the images that the ZoneMinder client generates are stored", + help => "ZoneMinder generates a myriad of images, mosty of which are associated with events. For those that aren't this is where they go.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_DIR_SOUNDS", + default => "sounds", + description => "Directory to the sounds that the ZoneMinder client can use", + help => "ZoneMinder can optionally play a sound file when an alarm is detected. This indicates where (relative to the web root) to look for this file.", + type => $types{directory}, + category => "paths", + }, + { + name => "ZM_PATH_ZMS", + default => "/cgi-bin/nph-zms", + description => "Web path to zms streaming server", + help => "The ZoneMinder streaming server is required to send streamed images to your browser. It will be installed into the cgi-bin path given at configuration time. This option determines what the web path to the server is rather than the local path on your machine. Ordinarily the streaming server runs in parser-header mode however if you experience problems with streaming you can change this to non-parsed-header (nph) mode by changing 'zms' to 'nph-zms'.", + type => $types{rel_path}, + category => "paths", + }, + { + name => "ZM_COLOUR_JPEG_FILES", + default => "yes", + description => "Colourise greyscale JPEG files", + help => "Cameras that capture in greyscale can write their captured images to jpeg files with a corresponding greyscale colour space. This saves a small amount of disk space over colour ones. However some tools such as ffmpeg either fail to work with this colour space or have to convert it beforehand. Setting this option to yes uses up a little more space but makes creation of MPEG files much faster.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_ADD_JPEG_COMMENTS", + default => "no", + description => "Add jpeg timestamp annotations as file header comments", + help => "JPEG files may have a number of extra fields added to the file header. The comment field may have any kind of text added. This options allows you to have the same text that is used to annotate the image additionally included as a file header comment. If you archive event images to other locations this may help you locate images for particular events or times if you use software that can read comment headers.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_JPEG_FILE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the saved event files (1-100)", + help => "When ZoneMinder detects an event it will save the images associated with that event to files. These files are in the JPEG format and can be viewed or streamed later. This option specifies what image quality should be used to save these files. A higher number means better quality but less compression so will take up more disk space and take longer to view over a slow connection. By contrast a low number means smaller, quicker to view, files but at the price of lower quality images. This setting applies to all images written except if the capture image has caused an alarm and the alarm file quality option is set at a higher value when that is used instead.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_JPEG_ALARM_FILE_QUALITY", + default => "0", + description => "Set the JPEG quality setting for the saved event files during an alarm (1-100)", + help => "This value is equivalent to the regular jpeg file quality setting above except that it only applies to images saved while in an alarm state and then only if this value is set to a higher quality setting than the ordinary file setting. If set to a lower value then it is ignored. Thus leaving it at the default of 0 effectively means to use the regular file quality setting for all saved images. This is to prevent acccidentally saving important images at a worse quality setting.", + type => $types{integer}, + category => "images", + }, + # Deprecated, now stream quality + { + name => "ZM_JPEG_IMAGE_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_JPEG_STREAM_QUALITY", + default => "70", + description => "Set the JPEG quality setting for the streamed 'live' images (1-100)", + help => "When viewing a 'live' stream for a monitor ZoneMinder will grab an image from the buffer and encode it into JPEG format before sending it. This option specifies what image quality should be used to encode these images. A higher number means better quality but less compression so will take longer to view over a slow connection. By contrast a low number means quicker to view images but at the price of lower quality images. This option does not apply when viewing events or still images as these are usually just read from disk and so will be encoded at the quality specified by the previous options.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_MPEG_TIMED_FRAMES", + default => "yes", + description => "Tag video frames with a timestamp for more realistic streaming", + help => "When using streamed MPEG based video, either for live monitor streams or events, ZoneMinder can send the streams in two ways. If this option is selected then the timestamp for each frame, taken from it's capture time, is included in the stream. This means that where the frame rate varies, for instance around an alarm, the stream will still maintain it's 'real' timing. If this option is not selected then an approximate frame rate is calculated and that is used to schedule frames instead. This option should be selected unless you encounter problems with your preferred streaming method.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_MPEG_LIVE_FORMAT", + default => "swf", + description => "What format 'live' video streams are played in", + help => "When using MPEG mode ZoneMinder can output live video. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player but I'm currently not sure what, if anything, works on a Linux platform. If you find out please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_MPEG_REPLAY_FORMAT", + default => "swf", + description => "What format 'replay' video streams are played in", + help => "When using MPEG mode ZoneMinder can replay events in encoded video format. However what formats are handled by the browser varies greatly between machines. This option allows you to specify a video format using a file extension format, so you would just enter the extension of the file type you would like and the rest is determined from that. The default of 'asf' works well under Windows with Windows Media Player and 'mpg', or 'avi' etc should work under Linux. If you know any more then please let me know! If this option is left blank then live streams will revert to being in motion jpeg format", + type => $types{string}, + category => "images", + }, + { + name => "ZM_RAND_STREAM", + default => "yes", + description => "Add a random string to prevent caching of streams", + help => "Some browsers can cache the streams used by ZoneMinder. In order to prevent his a harmless random string can be appended to the url to make each invocation of the stream appear unique.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_OPT_CAMBOZOLA", + default => "no", + description => "Is the (optional) cambozola java streaming client installed", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_CAMBOZOLA", + default => "cambozola.jar", + description => "Web path to (optional) cambozola java streaming client", + help => "Cambozola is a handy low fat cheese flavoured Java applet that ZoneMinder uses to view image streams on browsers such as Internet Explorer that don't natively support this format. If you use this browser it is highly recommended to install this from http://www.charliemouse.com/code/cambozola/ however if it is not installed still images at a lower refresh rate can still be viewed. Leave this as 'cambozola.jar' if cambozola is installed in the same directory as the ZoneMinder web client files.", + requires => [ { name=>"ZM_OPT_CAMBOZOLA", value=>"yes" } ], + type => $types{rel_path}, + category => "images", + }, + { + name => "ZM_RELOAD_CAMBOZOLA", + default => "0", + description => "After how many seconds should Cambozola be reloaded in live view", + help => "Cambozola allows for the viewing of streaming MJPEG however it caches the entire stream into cache space on the computer, setting this to a number > 0 will cause it to automatically reload after that many seconds to avoid filling up a hard drive.", + type => $types{integer}, + category => "images", + }, + { + name => "ZM_TIMESTAMP_ON_CAPTURE", + default => "yes", + description => "Timestamp images as soon as they are captured", + help => "ZoneMinder can add a timestamp to images in two ways. The default method, when this option is set, is that each image is timestamped immediately when captured and so the image held in memory is marked right away. The second method does not timestamp the images until they are either saved as part of an event or accessed over the web. The timestamp used in both methods will contain the same time as this is preserved along with the image. The first method ensures that an image is timestamped regardless of any other circumstances but will result in all images being timestamped even those never saved or viewed. The second method necessitates that saved images are copied before being saved otherwise two timestamps perhaps at different scales may be applied. This has the (perhaps) desirable side effect that the timestamp is always applied at the same resolution so an image that has scaling applied will still have a legible and correctly scaled timestamp.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CPU_EXTENSIONS", + default => "yes", + description => "Use advanced CPU extensions to increase performance", + help => "When advanced processor extensions such as SSE2 or SSSE3 are available, ZoneMinder can use them, which should increase performance and reduce system load. Enabling this option on processors that do not support the advanced processors extensions used by ZoneMinder is harmless and will have no effect.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_FAST_IMAGE_BLENDS", + default => "yes", + description => "Use a fast algorithm to blend the reference image", + help => "To detect alarms ZoneMinder needs to blend the captured image with the stored reference image to update it for comparison with the next image. The reference blend percentage specified for the monitor controls how much the new image affects the reference image. There are two methods that are available for this. If this option is set then fast calculation which does not use any multiplication or division is used. This calculation is extremely fast, however it limits the possible blend percentages to 50%, 25%, 12.5%, 6.25%, 3.25% and 1.5%. Any other blend percentage will be rounded to the nearest possible one. The alternative is to switch this option off and use standard blending instead, which is slower.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_ADAPTIVE_SKIP", + default => "yes", + description => "Should frame analysis try and be efficient in skipping frames", + help => "In previous versions of ZoneMinder the analysis daemon would attempt to keep up with the capture daemon by processing the last captured frame on each pass. This would sometimes have the undesirable side-effect of missing a chunk of the initial activity that caused the alarm because the pre-alarm frames would all have to be written to disk and the database before processing the next frame, leading to some delay between the first and second event frames. Setting this option enables a newer adaptive algorithm where the analysis daemon attempts to process as many captured frames as possible, only skipping frames when in danger of the capture daemon overwriting yet to be processed frames. This skip is variable depending on the size of the ring buffer and the amount of space left in it. Enabling this option will give you much better coverage of the beginning of alarms whilst biasing out any skipped frames towards the middle or end of the event. However you should be aware that this will have the effect of making the analysis daemon run somewhat behind the capture daemon during events and for particularly fast rates of capture it is possible for the adaptive algorithm to be overwhelmed and not have time to react to a rapid build up of pending frames and thus for a buffer overrun condition to occur.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_BLEND_ALARMED_IMAGES", + default => "yes", + description => "Blend alarmed images to update the reference image", + help => "To detect alarms ZoneMinder compares an image with a reference image which is formed from a composite of the previous images. This option determines whether images that cause events are included in this process. Doing so may increase the precision of the alarmed region but can cause problems if wholescale lighting changes cause alarms as this would not get fed back into the image and an alarm may persist indefinately. A better way to achive the same effect in most cases is to lower substantially the reference blend percentage in specific monitors.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_MAX_SUSPEND_TIME", + default => "30", + description => "Maximum time that a monitor may have motion detection suspended", + help => "ZoneMinder allows monitors to have motion detection to be suspended, for instance while panning a camera. Ordinarily this relies on the operator resuming motion detection afterwards as failure to do so can leave a monitor in a permanently suspended state. This setting allows you to set a maximum time which a camera may be suspended for before it automatically resumes motion detection. This time can be extended by subsequent suspend indications after the first so continuous camera movement will also occur while the monitor is suspended.", + type => $types{integer}, + category => "config", + }, + # Deprecated, really no longer necessary + { + name => "ZM_OPT_REMOTE_CAMERAS", + default => "no", + description => "Are you going to use remote/networked cameras", + help => "ZoneMinder can work with both local cameras, ie. those attached physically to your computer and remote or network cameras. If you will be using networked cameras select this option.", + type => $types{boolean}, + category => "hidden", + }, + # Deprecated, now set on a per monitor basis using the Method field + { + name => "ZM_NETCAM_REGEXPS", + default => "yes", + description => "Use regular expression matching with network cameras", + help => "Traditionally ZoneMinder has used complex regular regular expressions to handle the multitude of formats that network cameras produce. In versions from 1.21.1 the default is to use a simpler and faster built in pattern matching methodology. This works well with most networks cameras but if you have problems you can try the older, but more flexible, regular expression based method by selecting this option. Note, to use this method you must have libpcre installed on your system.", + requires => [ { name => "ZM_OPT_REMOTE_CAMERAS", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_HTTP_VERSION", + default => "1.1", + description => "The version of HTTP that ZoneMinder will use to connect", + help => "ZoneMinder can communicate with network cameras using either of the HTTP/1.1 or HTTP/1.0 standard. A server will normally fall back to the version it supports iwht no problem so this should usually by left at the default. However it can be changed to HTTP/1.0 if necessary to resolve particular issues.", + type => { db_type=>"string", hint=>"1.1|1.0", pattern=>qr|^(1\.[01])$|, format=>q( $1?$1:"" ) }, + category => "network", + }, + { + name => "ZM_HTTP_UA", + default => "ZoneMinder", + description => "The user agent that ZoneMinder uses to identify itself", + help => "When ZoneMinder communicates with remote cameras it will identify itself using this string and it's version number. This is normally sufficient, however if a particular cameras expects only to communicate with certain browsers then this can be changed to a different string identifying ZoneMinder as Internet Explorer or Netscape etc.", + type => $types{string}, + category => "network", + }, + { + name => "ZM_HTTP_TIMEOUT", + default => "2500", + description => "How long ZoneMinder waits before giving up on images (milliseconds)", + help => "When retrieving remote images ZoneMinder will wait for this length of time before deciding that an image is not going to arrive and taking steps to retry. This timeout is in milliseconds (1000 per second) and will apply to each part of an image if it is not sent in one whole chunk.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MIN_RTP_PORT", + default => "40200", + description => "Minimum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the minimum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_MAX_RTP_PORT", + default => "40499", + description => "Maximum port that ZoneMinder will listen for RTP traffic on", + help => "When ZoneMinder communicates with MPEG4 capable cameras using RTP with the unicast method it must open ports for the camera to connect back to for control and streaming purposes. This setting specifies the maximum port number that ZoneMinder will use. Ordinarily two adjacent ports are used for each camera, one for control packets and one for data packets. This port should be set to an even number, you may also need to open up a hole in your firewall to allow cameras to connect back if you wish to use unicasting. You should also ensure that you have opened up at least two ports for each monitor that will be connecting to unicasting network cameras.", + type => $types{integer}, + category => "network", + }, + { + name => "ZM_OPT_FFMPEG", + default => "@OPT_FFMPEG@", + description => "Is the ffmpeg video encoder/decoder installed", + help => "ZoneMinder can optionally encode a series of video images into an MPEG encoded movie file for viewing, downloading or storage. This option allows you to specify whether you have the ffmpeg tools installed. Note that creating MPEG files can be fairly CPU and disk intensive and is not a required option as events can still be reviewed as video streams without it.", + type => $types{boolean}, + category => "images", + }, + { + name => "ZM_PATH_FFMPEG", + default => "@PATH_FFMPEG@", + description => "Path to (optional) ffmpeg mpeg encoder", + help => "This path should point to where ffmpeg has been installed.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{abs_path}, + category => "images", + }, + { + name => "ZM_FFMPEG_INPUT_OPTIONS", + default => "", + description => "Additional input options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the input to ffmpeg (options that are given before the -i option). Check the ffmpeg documentation for a full list of options which may be used here.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_OUTPUT_OPTIONS", + default => "-r 25", + description => "Additional output options to ffmpeg", + help => "Ffmpeg can take many options on the command line to control the quality of video produced. This option allows you to specify your own set that apply to the output from ffmpeg (options that are given after the -i option). Check the ffmpeg documentation for a full list of options which may be used here. The most common one will often be to force an output frame rate supported by the video encoder.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_FFMPEG_FORMATS", + default => "mpg mpeg wmv asf avi* mov swf 3gp**", + description => "Formats to allow for ffmpeg video generation", + help => "Ffmpeg can generate video in many different formats. This option allows you to list the ones you want to be able to select. As new formats are supported by ffmpeg you can add them here and be able to use them immediately. Adding a '*' after a format indicates that this will be the default format used for web video, adding '**' defines the default format for phone video.", + requires => [ { name=>"ZM_OPT_FFMPEG", value=>"yes" } ], + type => $types{string}, + category => "images", + }, + { + name => "ZM_LOG_LEVEL_SYSLOG", + default => "0", + description => "Save logging output to the system log", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to the system log. ZoneMinder binaries have always logged to the system log but now scripts and web logging is also included. To preserve the previous behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_FILE", + default => "-5", + description => "Save logging output to component files", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that goes to individual log files written by specific components. This is how logging worked previously and although useful for tracking down issues in specific components it also resulted in many disparate log files. To preserve this behaviour you should ensure this value is set to Info or Warning. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance though file output has less impact than the other options. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_WEBLOG", + default => "-5", + description => "Save logging output to the weblog", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output from the web interface that goes to the httpd error log. Note that only web logging from PHP and JavaScript files is included and so this option is really only useful for investigating specific issues with those components. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_LEVEL_DATABASE", + default => "0", + description => "Save logging output to the database", + help => "ZoneMinder logging is now more more integrated between components and allows you to specify the destination for logging output and the individual levels for each. This option lets you control the level of logging output that is written to the database. This is a new option which can make viewing logging output easier and more intuitive and also makes it easier to get an overall impression of how the system is performing. If you have a large or very busy system then it is possible that use of this option may slow your system down if the table becomes very large. Ensure you use the LOG_DATABASE_LIMIT option to keep the table to a manageable size. This option controls the maximum level of logging that will be written, so Info includes Warnings and Errors etc. To disable entirely, set this option to None. You should use caution when setting this option to Debug as it can affect severely affect system performance. If you want debug you will also need to set a level and component below", + type => { db_type=>"integer", hint=>"None=-5|Panic=-4|Fatal=-3|Error=-2|Warning=-1|Info=0|Debug=1", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DATABASE_LIMIT", + default => "7 day", + description => "Maximum number of log entries to retain", + help => "If you are using database logging then it is possible to quickly build up a large number of entries in the Logs table. This option allows you to specify how many of these entries are kept. If you set this option to a number greater than zero then that number is used to determine the maximum number of rows, less than or equal to zero indicates no limit and is not recommended. You can also set this value to time values such as ' day' which will limit the log entries to those newer than that time. You can specify 'hour', 'day', 'week', 'month' and 'year', note that the values should be singular (no 's' at the end). The Logs table is pruned periodically so it is possible for more than the expected number of rows to be present briefly in the meantime.", + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG", + default => "no", + description => "Switch debugging on", + help => "ZoneMinder components usually support debug logging available to help with diagnosing problems. Binary components have several levels of debug whereas more other components have only one. Normally this is disabled to minimise performance penalties and avoid filling logs too quickly. This option lets you switch on other options that allow you to configure additional debug information to be output. Components will pick up this instruction when they are restarted.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_TARGET", + default => "", + description => "What components should have extra debug enabled", + help => "There are three scopes of debug available. Leaving this option blank means that all components will use extra debug (not recommended). Setting this option to '_', e.g. _zmc, will limit extra debug to that component only. Setting this option to '__', e.g. '_zmc_m1' will limit extra debug to that instance of the component only. This is ordinarily what you probably want to do. To debug scripts use their names without the .pl extension, e.g. '_zmvideo' and to debug issues with the web interface use '_web'. You can specify multiple targets by separating them with '|' characters.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_LEVEL", + default => 1, + description => "What level of extra debug should be enabled", + help => "There are 9 levels of debug available, with higher numbers being more debug and level 0 being no debug. However not all levels are used by all components. Also if there is debug at a high level it is usually likely to be output at such a volume that it may obstruct normal operation. For this reason you should set the level carefully and cautiously until the degree of debug you wish to see is present. Scripts and the web interface only have one level so this is an on/off type option for them.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => { db_type=>"integer", hint=>"1|2|3|4|5|6|7|8|9", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "logging", + }, + { + name => "ZM_LOG_DEBUG_FILE", + default => "@ZM_TMPDIR@/zm_debug.log+", + description => "Where extra debug is output to", + help => "This option allows you to specify a different target for debug output. All components have a default log file which will norally be in /tmp or /var/log and this is where debug will be written to if this value is empty. Adding a path here will temporarily redirect debug, and other logging output, to this file. This option is a simple filename and you are debugging several components then they will all try and write to the same file with undesirable consequences. Appending a '+' to the filename will cause the file to be created with a '.' suffix containing your process id. In this way debug from each run of a component is kept separate. This is the recommended setting as it will also prevent subsequent runs from overwriting the same log. You should ensure that permissions are set up to allow writing to the file and directory specified here.", + requires => [ { name => "ZM_LOG_DEBUG", value => "yes" } ], + type => $types{string}, + category => "logging", + }, + { + name => "ZM_LOG_CHECK_PERIOD", + default => "900", + description => "Time period used when calculating overall system health", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to indicate what period of historical events are used in this calculation. This value is expressed in seconds and is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_WAR_COUNT", + default => "1", + description => "Number of warnings indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alert state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_ERR_COUNT", + default => "1", + description => "Number of errors indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alert state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALERT_FAT_COUNT", + default => "0", + description => "Number of fatal error indicating system alert state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alert state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_WAR_COUNT", + default => "100", + description => "Number of warnings indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many warnings must have occurred within the defined time period to generate an overall system alarm state. A value of zero means warnings are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_ERR_COUNT", + default => "10", + description => "Number of errors indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many errors must have occurred within the defined time period to generate an overall system alarm state. A value of zero means errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_LOG_ALARM_FAT_COUNT", + default => "1", + description => "Number of fatal error indicating system alarm state", + help => "When ZoneMinder is logging events to the database it can retrospectively examine the number of warnings and errors that have occurred to calculate an overall state of system health. This option allows you to specify how many fatal errors (including panics) must have occurred within the defined time period to generate an overall system alarm state. A value of zero means fatal errors are not considered. This value is ignored if LOG_LEVEL_DATABASE is set to None.", + type => $types{integer}, + category => "logging", + }, + { + name => "ZM_RECORD_EVENT_STATS", + default => "yes", + description => "Record event statistical information, switch off if too slow", + help => "This version of ZoneMinder records detailed information about events in the Stats table. This can help in profiling what the optimum settings are for Zones though this is tricky at present. However in future releases this will be done more easily and intuitively, especially with a large sample of events. The default option of 'yes' allows this information to be collected now in readiness for this but if you are concerned about performance you can switch this off in which case no Stats information will be saved.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_RECORD_DIAG_IMAGES", + default => "no", + description => "Record intermediate alarm diagnostic images, can be very slow", + help => "In addition to recording event statistics you can also record the intermediate diagnostic images that display the results of the various checks and processing that occur when trying to determine if an alarm event has taken place. There are several of these images generated for each frame and zone for each alarm or alert frame so this can have a massive impact on performance. Only switch this setting on for debug or analysis purposes and remember to switch it off again once no longer required.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_DUMP_CORES", + default => "no", + description => "Create core files on unexpected process failure.", + help => "When an unrecoverable error occurs in a ZoneMinder binary process is has traditionally been trapped and the details written to logs to aid in remote analysis. However in some cases it is easier to diagnose the error if a core file, which is a memory dump of the process at the time of the error, is created. This can be interactively analysed in the debugger and may reveal more or better information than that available from the logs. This option is recommended for advanced users only otherwise leave at the default. Note using this option to trigger core files will mean that there will be no indication in the binary logs that a process has died, they will just stop, however the zmdc log will still contain an entry. Also note that you may have to explicitly enable core file creation on your system via the 'ulimit -c' command or other means otherwise no file will be created regardless of the value of this option.", + type => $types{boolean}, + category => "logging", + }, + { + name => "ZM_PATH_MAP", + default => "/dev/shm", + description => "Path to the mapped memory files that that ZoneMinder can use", + help => "ZoneMinder has historically used IPC shared memory for shared data between processes. This has it's advantages and limitations. This version of ZoneMinder can use an alternate method, mapped memory, instead with can be enabled with the --enable--mmap directive to configure. This requires less system configuration and is generally more flexible. However it requires each shared data segment to map onto a filesystem file. This option indicates where those mapped files go. You should ensure that this location has sufficient space for these files and for the best performance it should be a tmpfs file system or ramdisk otherwise disk access may render this method slower than the regular shared memory one.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SOCKS", + default => "@ZM_TMPDIR@", + description => "Path to the various Unix domain socket files that ZoneMinder uses", + help => "ZoneMinder generally uses Unix domain sockets where possible. This reduces the need for port assignments and prevents external applications from possibly compromising the daemons. However each Unix socket requires a .sock file to be created. This option indicates where those socket files go.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_LOGS", + default => "@ZM_LOGDIR@", + description => "Path to the various logs that the ZoneMinder daemons generate", + help => "There are various daemons that are used by ZoneMinder to perform various tasks. Most generate helpful log files and this is where they go. They can be deleted if not required for debugging.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_PATH_SWAP", + default => "@ZM_TMPDIR@", + description => "Path to location for temporary swap images used in streaming", + help => "Buffered playback requires temporary swap images to be stored for each instance of the streaming daemons. This option determines where these images will be stored. The images will actually be stored in sub directories beneath this location and will be automatically cleaned up after a period of time.", + type => $types{abs_path}, + category => "paths", + }, + { + name => "ZM_WEB_TITLE_PREFIX", + default => "ZM", + description => "The title prefix displayed on each window", + help => "If you have more than one installation of ZoneMinder it can be helpful to display different titles for each one. Changing this option allows you to customise the window titles to include further information to aid identification.", + type => $types{string}, + category => "web", + }, + { + name => "ZM_WEB_RESIZE_CONSOLE", + default => "yes", + description => "Should the console window resize itself to fit", + help => "Traditionally the main ZoneMinder web console window has resized itself to shrink to a size small enough to list only the monitors that are actually present. This is intended to make the window more unobtrusize but may not be to everyones tastes, especially if opened in a tab in browsers which support this kind if layout. Switch this option off to have the console window size left to the users preference", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_POPUP_ON_ALARM", + default => "yes", + description => "Should the monitor window jump to the top if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to pop to the front if an alarm occurs when the window is minimised or behind another window. This is most useful if your monitors are over doors for example when they can pop up if someone comes to the doorway.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_X10", + default => "no", + description => "Support interfacing with X10 devices", + help => "If you have an X10 Home Automation setup in your home you can use ZoneMinder to initiate or react to X10 signals if your computer has the appropriate interface controller. This option indicates whether X10 options will be available in the browser client.", + type => $types{boolean}, + category => "x10", + }, + { + name => "ZM_X10_DEVICE", + default => "/dev/ttyS0", + description => "What device is your X10 controller connected on", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "If you have an X10 controller device (e.g. XM10U) connected to your computer this option details which port it is conected on, the default of /dev/ttyS0 maps to serial or com port 1.", + type => $types{abs_path}, + category => "x10", + }, + { + name => "ZM_X10_HOUSE_CODE", + default => "A", + description => "What X10 house code should be used", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "X10 devices are grouped together by identifying them as all belonging to one House Code. This option details what that is. It should be a single letter between A and P.", + type => { db_type=>"string", hint=>"A-P", pattern=>qr|^([A-P])|i, format=>q( uc($1) ) }, + category => "x10", + }, + { + name => "ZM_X10_DB_RELOAD_INTERVAL", + default => "60", + description => "How often (in seconds) the X10 daemon reloads the monitors from the database", + requires => [ { name => "ZM_OPT_X10", value => "yes" } ], + help => "The zmx10 daemon periodically checks the database to find out what X10 events trigger, or result from, alarms. This option determines how frequently this check occurs, unless you change this area frequently this can be a fairly large value.", + type => $types{integer}, + category => "x10", + }, + { + name => "ZM_WEB_SOUND_ON_ALARM", + default => "no", + description => "Should the monitor window play a sound if an alarm occurs", + help => "When viewing a live monitor stream you can specify whether you want the window to play a sound to alert you if an alarm occurs.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_ALARM_SOUND", + default => "", + description => "The sound to play on alarm, put this in the sounds directory", + help => "You can specify a sound file to play if an alarm occurs whilst you are watching a live monitor stream. So long as your browser understands the format it does not need to be any particular type. This file should be placed in the sounds directory defined earlier.", + type => $types{file}, + requires => [ { name => "ZM_WEB_SOUND_ON_ALARM", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_COMPACT_MONTAGE", + default => "no", + description => "Compact the montage view by removing extra detail", + help => "The montage view shows the output of all of your active monitors in one window. This include a small menu and status information for each one. This can increase the web traffic and make the window larger than may be desired. Setting this option on removes all this extraneous information and just displays the images.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_OPT_FAST_DELETE", + default => "yes", + description => "Delete only event database records for speed", + help => "Normally an event created as the result of an alarm consists of entries in one or more database tables plus the various files associated with it. When deleting events in the browser it can take a long time to remove all of this if your are trying to do a lot of events at once. It is recommended that you set this option which means that the browser client only deletes the key entries in the events table, which means the events will no longer appear in the listing, and leaves the zmaudit daemon to clear up the rest later.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_STRICT_VIDEO_CONFIG", + default => "yes", + description => "Allow errors in setting video config to be fatal", + help => "With some video devices errors can be reported in setting the various video attributes when in fact the operation was successful. Switching this option off will still allow these errors to be reported but will not cause them to kill the video capture daemon. Note however that doing this will cause all errors to be ignored including those which are genuine and which may cause the video capture to not function correctly. Use this option with caution.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_SIGNAL_CHECK_POINTS", + default => "10", + description => "How many points in a captured image to check for signal loss", + help => "For locally attached video cameras ZoneMinder can check for signal loss by looking at a number of random points on each captured image. If all of these points are set to the same fixed colour then the camera is assumed to have lost signal. When this happens any open events are closed and a short one frame signal loss event is generated, as is another when the signal returns. This option defines how many points on each image to check. Note that this is a maximum, any points found to not have the check colour will abort any further checks so in most cases on a couple of points will actually be checked. Network and file based cameras are never checked.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_V4L_MULTI_BUFFER", + default => "yes", + description => "Use more than one buffer for Video 4 Linux devices", + help => "Performance when using Video 4 Linux devices is usually best if multiple buffers are used allowing the next image to be captured while the previous one is being processed. If you have multiple devices on a card sharing one input that requires switching then this approach can sometimes cause frames from one source to be mixed up with frames from another. Switching this option off prevents multi buffering resulting in slower but more stable image capture. This option is ignored for non-local cameras or if only one input is present on a capture chip. This option addresses a similar problem to the ZM_CAPTURES_PER_FRAME option and you should normally change the value of only one of the options at a time.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_CAPTURES_PER_FRAME", + default => "1", + description => "How many images are captured per returned frame, for shared local cameras", + help => "If you are using cameras attached to a video capture card which forces multiple inputs to share one capture chip, it can sometimes produce images with interlaced frames reversed resulting in poor image quality and a distinctive comb edge appearance. Increasing this setting allows you to force additional image captures before one is selected as the captured frame. This allows the capture hardware to 'settle down' and produce better quality images at the price of lesser capture rates. This option has no effect on (a) network cameras, or (b) where multiple inputs do not share a capture chip. This option addresses a similar problem to the ZM_V4L_MULTI_BUFFER option and you should normally change the value of only one of the options at a time.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_FILTER_RELOAD_DELAY", + default => "300", + description => "How often (in seconds) filters are reloaded in zmfilter", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are reloaded from the database to get the latest versions or new filters. If you don't change filters very often this value can be set to a large value.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FILTER_EXECUTE_INTERVAL", + default => "60", + description => "How often (in seconds) to run automatic saved filters", + help => "ZoneMinder allows you to save filters to the database which allow events that match certain criteria to be emailed, deleted or uploaded to a remote machine etc. The zmfilter daemon loads these and does the actual operation. This option determines how often the filters are executed on the saved event in the database. If you want a rapid response to new events this should be a smaller value, however this may increase the overall load on the system and affect performance of other elements.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_UPLOAD", + default => "no", + description => "Should ZoneMinder support uploading events from filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should be uploaded to a remote server for archiving. This option specifies whether this functionality should be available", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_FORMAT", + default => "tar", + description => "What format the uploaded events should be created in.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "Uploaded events may be stored in either .tar or .zip format, this option specifies which. Note that to use this you will need to have the Archive::Tar and/or Archive::Zip perl modules installed.", + type => { db_type=>"string", hint=>"tar|zip", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^t/ ? "tar" : "zip" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_COMPRESS", + default => "no", + description => "Should archive files be compressed", + help => "When the archive files are created they can be compressed. However in general since the images are compressed already this saves only a minimal amount of space versus utilising more CPU in their creation. Only enable if you have CPU to waste and are limited in disk space on your remote server or bandwidth.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_ARCH_ANALYSE", + default => "no", + description => "Include the analysis files in the archive", + help => "When the archive files are created they can contain either just the captured frames or both the captured frames and, for frames that caused an alarm, the analysed image with the changed area highlighted. This option controls files are included. Only include analysed frames if you have a high bandwidth connection to the remote server or if you need help in figuring out what caused an alarm in the first place as archives with these files in can be considerably larger.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PROTOCOL", + default => "ftp", + description => "What protocol to use to upload events", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "ZoneMinder can upload events to a remote server using either FTP or SFTP. Regular FTP is widely supported but not necessarily very secure whereas SFTP (Secure FTP) runs over an ssh connection and so is encrypted and uses regular ssh ports. Note that to use this you will need to have the appropriate perl module, either Net::FTP or Net::SFTP installed depending on your choice.", + type => { db_type=>"string", hint=>"ftp|sftp", pattern=>qr|^([tz])|i, format=>q( $1 =~ /^f/ ? "ftp" : "sftp" ) }, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_HOST", + default => "", + description => "The remote server to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_HOST", + default => "", + description => "The remote server to upload events to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the name, or ip address, of the server to use.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{hostname}, + category => "upload", + }, + { + name => "ZM_UPLOAD_PORT", + default => "", + description => "The port on the remote upload server, if not the default (SFTP only)", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are using the SFTP protocol then this option allows you to specify a particular port to use for connection. If this option is left blank then the default, port 22, is used. This option is ignored for FTP uploads.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_USER", + default => "", + description => "Your ftp username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the username that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_USER", + default => "", + description => "Remote server username", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the username that ZoneMinder should use to log in for transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{alphanum}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASS", + default => "", + description => "Your ftp password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the password that ZoneMinder should use to log in for ftp transfer.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_PASS", + default => "", + description => "Remote server password", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the password that ZoneMinder should use to log in for transfer. If you are using certicate based logins for SFTP servers you can leave this option blank.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{string}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_LOC_DIR", + default => "@ZM_TMPDIR@", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_LOC_DIR", + default => "@ZM_TMPDIR@", + description => "The local directory in which to create upload files", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the local directory that ZoneMinder should use for temporary upload files. These are files that are created from events, uploaded and then deleted.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{abs_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_REM_DIR", + default => "", + description => "The remote directory to upload to", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the remote directory that ZoneMinder should use to upload event files to.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{rel_path}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates the maximum ftp inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_TIMEOUT", + default => "120", + description => "How long to allow the transfer to take for each file", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. This option indicates the maximum inactivity timeout (in seconds) that should be tolerated before ZoneMinder determines that the transfer has failed and closes down the connection.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{integer}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_PASSIVE", + default => "yes", + description => "Use passive ftp when uploading", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. This option indicates that ftp transfers should be done in passive mode. This uses a single connection for all ftp activity and, whilst slower than active transfers, is more robust and likely to work from behind filewalls. This option is ignored for SFTP transfers.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + help => "If your computer is behind a firewall or proxy you may need to set FTP to passive mode. In fact for simple transfers it makes little sense to do otherwise anyway but you can set this to 'No' if you wish.", + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_UPLOAD_FTP_DEBUG", + default => "no", + description => "Switch ftp debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote ftp server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be included in the zmfilter log file.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_UPLOAD_DEBUG", + default => "no", + description => "Switch upload debugging on", + help => "You can use filters to instruct ZoneMinder to upload events to a remote server. If you are having (or expecting) troubles with uploading events then setting this to 'yes' permits additional information to be generated by the underlying transfer modules and included in the logs.", + requires => [ { name => "ZM_OPT_UPLOAD", value => "yes" } ], + type => $types{boolean}, + category => "upload", + }, + { + name => "ZM_OPT_EMAIL", + default => "no", + description => "Should ZoneMinder email you details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details emailed to you at a designated email address. This will allow you to be notified of events as soon as they occur and also to quickly view the events directly. This option specifies whether this functionality should be available. The email created with this option can be any size and is intended to be sent to a regular email reader rather than a mobile device.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_EMAIL_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)" +body = " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder"', + description => "The text of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_EMAIL_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)", + description => "The subject of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the subject of the email that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_EMAIL_BODY", + default => " +Hello, + +An alarm has been detected on your installation of the ZoneMinder. + +The details are as follows :- + + Monitor : %MN% + Event Id : %EI% + Length : %EL% + Frames : %EF% (%EFA%) + Scores : t%EST% m%ESM% a%ESA% + +This alarm was matched by the %FN% filter and can be viewed at %EPS% + +ZoneMinder", + description => "The body of the email used to send matching event details", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" } ], + help => "This option is used to define the content of the email that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_OPT_MESSAGE", + default => "no", + description => "Should ZoneMinder message you with details of events that match corresponding filters", + help => "In ZoneMinder you can create event filters that specify whether events that match certain criteria should have their details sent to you at a designated short message email address. This will allow you to be notified of events as soon as they occur. This option specifies whether this functionality should be available. The email created by this option will be brief and is intended to be sent to an SMS gateway or a minimal mail reader such as a mobile device or phone rather than a regular email reader.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_MESSAGE_ADDRESS", + default => "", + description => "The email address to send matching event details to", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the short message email address that any events that match the appropriate filters will be sent to.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_MESSAGE_TEXT", + default => 'subject = "ZoneMinder: Alarm - %MN%-%EI%" +body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score."', + description => "The text of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "hidden", + }, + { + name => "ZM_MESSAGE_SUBJECT", + default => "ZoneMinder: Alarm - %MN%-%EI%", + description => "The subject of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the subject of the message that is sent for any events that match the appropriate filters.", + type => $types{string}, + category => "mail", + }, + { + name => "ZM_MESSAGE_BODY", + default => "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.", + description => "The body of the message used to send matching event details", + requires => [ { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "This option is used to define the content of the message that is sent for any events that match the appropriate filters.", + type => $types{text}, + category => "mail", + }, + { + name => "ZM_NEW_MAIL_MODULES", + default => "no", + description => "Use a newer perl method to send emails", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "Traditionally ZoneMinder has used the MIME::Entity perl module to construct and send notification emails and messages. Some people have reported problems with this module not being present at all or flexible enough for their needs. If you are one of those people this option allows you to select a new mailing method using MIME::Lite and Net::SMTP instead. This method was contributed by Ross Melin and should work for everyone but has not been extensively tested so currently is not selected by default.", + type => $types{boolean}, + category => "mail", + }, + { + name => "ZM_EMAIL_HOST", + default => "localhost", + description => "The host address of your SMTP mail server", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "If you have chosen SMTP as the method by which to send notification emails or messages then this option allows you to choose which SMTP server to use to send them. The default of localhost may work if you have the sendmail, exim or a similar daemon running however you may wish to enter your ISP's SMTP mail server here.", + type => $types{hostname}, + category => "mail", + }, + { + name => "ZM_FROM_EMAIL", + default => "", + description => "The email address you wish your event notifications to originate from", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can appear to come from a designated email address to help you with mail filtering etc. An address of something like ZoneMinder\@your.domain is recommended.", + type => $types{email}, + category => "mail", + }, + { + name => "ZM_URL", + default => "", + description => "The URL of your ZoneMinder installation", + requires => [ { name => "ZM_OPT_EMAIL", value => "yes" }, { name => "ZM_OPT_MESSAGE", value => "yes" } ], + help => "The emails or messages that will be sent to you informing you of events can include a link to the events themselves for easy viewing. If you intend to use this feature then set this option to the url of your installation as it would appear from where you read your email, e.g. http://host.your.domain/zm.php.", + type => $types{url}, + category => "mail", + }, + { + name => "ZM_MAX_RESTART_DELAY", + default => "600", + description => "Maximum delay (in seconds) for daemon restart attempts.", + help => "The zmdc (zm daemon control) process controls when processeses are started or stopped and will attempt to restart any that fail. If a daemon fails frequently then a delay is introduced between each restart attempt. If the daemon stills fails then this delay is increased to prevent extra load being placed on the system by continual restarts. This option controls what this maximum delay is.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_CHECK_INTERVAL", + default => "10", + description => "How often to check the capture daemons have not locked up", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines how often the daemons are checked.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_WATCH_MAX_DELAY", + default => "5", + description => "The maximum delay allowed since the last captured image", + help => "The zmwatch daemon checks the image capture performance of the capture daemons to ensure that they have not locked up (rarely a sync error may occur which blocks indefinately). This option determines the maximum delay to allow since the last captured frame. The daemon will be restarted if it has not captured any images after this period though the actual restart may take slightly longer in conjunction with the check interval value above.", + type => $types{decimal}, + category => "system", + }, + { + + name => "ZM_RUN_AUDIT", + default => "yes", + description => "Run zmaudit to check data consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. This option controls whether zmaudit is run in the background and performs these checks and fixes continuously. This is recommended for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to not have zmaudit running unconditionally and schedule occasional checks at other, more convenient, times.", + type => $types{boolean}, + category => "system", + }, + { + + name => "ZM_AUDIT_CHECK_INTERVAL", + default => "900", + description => "How often to check database and filesystem consistency", + help => "The zmaudit daemon exists to check that the saved information in the database and on the filesystem match and are consistent with each other. If an error occurs or if you are using 'fast deletes' it may be that database records are deleted but files remain. In this case, and similar, zmaudit will remove redundant information to synchronise the two data stores. The default check interval of 900 seconds (15 minutes) is fine for most systems however if you have a very large number of events the process of scanning the database and filesystem may take a long time and impact performance. In this case you may prefer to make this interval much larger to reduce the impact on your system. This option determines how often these checks are performed.", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_FORCED_ALARM_SCORE", + default => "255", + description => "Score to give forced alarms", + help => "The 'zmu' utility can be used to force an alarm on a monitor rather than rely on the motion detection algorithms. This option determines what score to give these alarms to distinguish them from regular ones. It must be 255 or less.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_BULK_FRAME_INTERVAL", + default => "100", + description => "How often a bulk frame should be written to the database", + help => "Traditionally ZoneMinder writes an entry into the Frames database table for each frame that is captured and saved. This works well in motion detection scenarios but when in a DVR situation ('Record' or 'Mocord' mode) this results in a huge number of frame writes and a lot of database and disk bandwidth for very little additional information. Setting this to a non-zero value will enabled ZoneMinder to group these non-alarm frames into one 'bulk' frame entry which saves a lot of bandwidth and space. The only disadvantage of this is that timing information for individual frames is lost but in constant frame rate situations this is usually not significant. This setting is ignored in Modect mode and individual frames are still written if an alarm occurs in Mocord mode also.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_EVENT_CLOSE_MODE", + default => "idle", + description => "When continuous events are closed.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section. This option controls what happens when an alarm occurs in Mocord mode. The 'time' setting means that the event will be closed at the end of the section regardless of alarm activity. The 'idle' setting means that the event will be closed at the end of the section if there is no alarm activity occuring at the time otherwise it will be closed once the alarm is over meaning the event may end up being longer than the normal section length. The 'alarm' setting means that if an alarm occurs during the event, the event will be closed once the alarm is over regardless of when this occurs. This has the effect of limiting the number of alarms to one per event and the events will be shorter than the section length if an alarm has occurred.", + type => $types{boolean}, + type => { db_type=>"string", hint=>"time|idle|alarm", pattern=>qr|^([tia])|i, format=>q( ($1 =~ /^t/) ? "time" : ($1 =~ /^i/ ? "idle" : "time" ) ) }, + category => "config", + }, + # Deprecated, superseded by event close mode + { + name => "ZM_FORCE_CLOSE_EVENTS", + default => "no", + description => "Close events at section ends.", + help => "When a monitor is running in a continuous recording mode (Record or Mocord) events are usually closed after a fixed period of time (the section length). However in Mocord mode it is possible that motion detection may occur near the end of a section and ordinarily this will prevent the event being closed until the motion has ceased. Switching this option on will force the event closed at the specified time regardless of any motion activity.", + type => $types{boolean}, + category => "hidden", + }, + { + name => "ZM_CREATE_ANALYSIS_IMAGES", + default => "yes", + description => "Create analysed alarm images with motion outlined", + help => "By default during an alarm ZoneMinder records both the raw captured image and one that has been analysed and had areas where motion was detected outlined. This can be very useful during zone configuration or in analysing why events occured. However it also incurs some overhead and in a stable system may no longer be necessary. This parameter allows you to switch the generation of these images off.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_WEIGHTED_ALARM_CENTRES", + default => "no", + description => "Use a weighted algorithm to calculate the centre of an alarm", + help => "ZoneMinder will always calculate the centre point of an alarm in a zone to give some indication of where on the screen it is. This can be used by the experimental motion tracking feature or your own custom extensions. In the alarmed or filtered pixels mode this is a simple midpoint between the extents of the detected pxiesl. However in the blob method this can instead be calculated using weighted pixel locations to give more accurate positioning for irregularly shaped blobs. This method, while more precise is also slower and so is turned off by default.", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_EVENT_IMAGE_DIGITS", + default => "3", + description => "How many significant digits are used in event image numbering", + help => "As event images are captured they are stored to the filesystem with a numerical index. By default this index has three digits so the numbers start 001, 002 etc. This works works for most scenarios as events with more than 999 frames are rarely captured. However if you have extremely long events and use external applications then you may wish to increase this to ensure correct sorting of images in listings etc. Warning, increasing this value on a live system may render existing events unviewable as the event will have been saved with the previous scheme. Decreasing this value should have no ill effects.", + type => $types{integer}, + category => "config", + }, + { + name => "ZM_DEFAULT_ASPECT_RATIO", + default => "4:3", + description => "The default width:height aspect ratio used in monitors", + help => "When specifying the dimensions of monitors you can click a checkbox to ensure that the width stays in the correct ratio to the height, or vice versa. This setting allows you to indicate what the ratio of these settings should be. This should be specified in the format : and the default of 4:3 normally be acceptable but 11:9 is another common setting. If the checkbox is not clicked when specifying monitor dimensions this setting has no effect.", + type => $types{string}, + category => "config", + }, + { + name => "ZM_USER_SELF_EDIT", + default => "no", + description => "Allow unprivileged users to change their details", + help => "Ordinarily only users with system edit privilege are able to change users details. Switching this option on allows ordinary users to change their passwords and their language settings", + type => $types{boolean}, + category => "config", + }, + { + name => "ZM_OPT_FRAME_SERVER", + default => "no", + description => "Should analysis farm out the writing of images to disk", + #requires => [ { name => "ZM_OPT_ADAPTIVE_SKIP", value => "yes" } ], + help => "In some circumstances it is possible for a slow disk to take so long writing images to disk that it causes the analysis daemon to fall behind especially during high frame rate events. Setting this option to yes enables a frame server daemon (zmf) which will be sent the images from the analysis daemon and will do the actual writing of images itself freeing up the analysis daemon to get on with other things. Should this transmission fail or other permanent or transient error occur, this function will fall back to the analysis daemon.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_FRAME_SOCKET_SIZE", + default => "0", + description => "Specify the frame server socket buffer size if non-standard", + requires => [ { name => "ZM_OPT_FRAME_SERVER", value => "yes" } ], + help => "For large captured images it is possible for the writes from the analysis daemon to the frame server to fail as the amount to be written exceeds the default buffer size. While the images are then written by the analysis daemon so no data is lost, it defeats the object of the frame server daemon in the first place. You can use this option to indicate that a larger buffer size should be used. Note that you may have to change the existing maximum socket buffer size on your system via sysctl (or in /proc/sys/net/core/wmem_max) to allow this new size to be set. Alternatively you can change the default buffer size on your system in the same way in which case that will be used with no change necessary in this option", + type => $types{integer}, + category => "system", + }, + { + name => "ZM_OPT_CONTROL", + default => "no", + description => "Support controllable (e.g. PTZ) cameras", + help => "ZoneMinder includes limited support for controllable cameras. A number of sample protocols are included and others can easily be added. If you wish to control your cameras via ZoneMinder then select this option otherwise if you only have static cameras or use other control methods then leave this option off.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_OPT_TRIGGERS", + default => "no", + description => "Interface external event triggers via socket or device files", + help => "ZoneMinder can interact with external systems which prompt or cancel alarms. This is done via the zmtrigger.pl script. This option indicates whether you want to use these external triggers. Most people will say no here.", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_CHECK_FOR_UPDATES", + default => "yes", + description => "Check with zoneminder.com for updated versions", + help => "From ZoneMinder version 1.17.0 onwards new versions are expected to be more frequent. To save checking manually for each new version ZoneMinder can check with the zoneminder.com website to determine the most recent release. These checks are infrequent, about once per week, and no personal or system information is transmitted other than your current version number. If you do not wish these checks to take place or your ZoneMinder system has no internet access you can switch these check off with this configuration variable", + type => $types{boolean}, + category => "system", + }, + { + name => "ZM_UPDATE_CHECK_PROXY", + default => "", + description => "Proxy url if required to access zoneminder.com", + help => "If you use a proxy to access the internet then ZoneMinder needs to know so it can access zoneminder.com to check for updates. If you do use a proxy enter the full proxy url here in the form of http://:/", + type => $types{string}, + category => "system", + }, + { + name => "ZM_SHM_KEY", + default => "0x7a6d0000", + description => "Shared memory root key to use", + help => "ZoneMinder uses shared memory to speed up communication between modules. To identify the right area to use shared memory keys are used. This option controls what the base key is, each monitor will have it's Id or'ed with this to get the actual key used. You will not normally need to change this value unless it clashes with another instance of ZoneMinder on the same machine. Only the first four hex digits are used, the lower four will be masked out and ignored.", + type => $types{hexadecimal}, + category => "system", + }, + # Deprecated, really no longer necessary + { + name => "ZM_WEB_REFRESH_METHOD", + default => "javascript", + description => "What method windows should use to refresh themselves", + help => "Many windows in Javascript need to refresh themselves to keep their information current. This option determines what method they should use to do this. Choosing 'javascript' means that each window will have a short JavaScript statement in with a timer to prompt the refresh. This is the most compatible method. Choosing 'http' means the refresh instruction is put in the HTTP header. This is a cleaner method but refreshes are interrupted or cancelled when a link in the window is clicked meaning that the window will no longer refresh and this would have to be done manually.", + type => { db_type=>"string", hint=>"javascript|http", pattern=>qr|^([jh])|i, format=>q( $1 =~ /^j/ ? "javascript" : "http" ) }, + category => "hidden", + }, + { + name => "ZM_WEB_EVENT_SORT_FIELD", + default => "DateTime", + description => "Default field the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what field is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"Id|Name|Cause|MonitorName|DateTime|Length|Frames|AlarmFrames|TotScore|AvgScore|MaxScore", pattern=>qr|.|, format=>q( $1 ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENT_SORT_ORDER", + default => "asc", + description => "Default order the event lists are sorted by", + help => "Events in lists can be initially ordered in any way you want. This option controls what order (ascending or descending) is used to sort them. You can modify this ordering from filters or by clicking on headings in the lists themselves. Bear in mind however that the 'Prev' and 'Next' links, when scrolling through events, relate to the ordering in the lists and so not always to time based ordering.", + type => { db_type=>"string", hint=>"asc|desc", pattern=>qr|^([ad])|i, format=>q( $1 =~ /^a/i ? "asc" : "desc" ) }, + category => "web", + }, + { + name => "ZM_WEB_EVENTS_PER_PAGE", + default => "25", + description => "How many events to list per page in paged mode", + help => "In the event list view you can either list all events or just a page at a time. This option controls how many events are listed per page in paged mode and how often to repeat the column headers in non-paged mode.", + type => $types{integer}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMBS", + default => "no", + description => "Display mini-thumbnails of event images in event lists", + help => "Ordinarily the event lists just display text details of the events to save space and time. By switching this option on you can also display small thumbnails to help you identify events of interest. The size of these thumbnails is controlled by the following two options.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_WIDTH", + default => "48", + description => "The width of the thumbnails that appear in the event lists", + help => "This options controls the width of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a height instead in the next option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_LIST_THUMB_HEIGHT", + default => "0", + description => "The height of the thumbnails that appear in the event lists", + help => "This options controls the height of the thumbnail images that appear in the event lists. It should be fairly small to fit in with the rest of the table. If you prefer you can specify a width instead in the previous option but you should only use one of the width or height and the other option should be set to zero. If both width and height are specified then width will be used and height ignored.", + type => $types{integer}, + requires => [ { name => "ZM_WEB_LIST_THUMBS", value => "yes" } ], + category => "web", + }, + { + name => "ZM_WEB_USE_OBJECT_TAGS", + default => "yes", + description => "Wrap embed in object tags for media content", + help => "There are two methods of including media content in web pages. The most common way is use the EMBED tag which is able to give some indication of the type of content. However this is not a standard part of HTML. The official method is to use OBJECT tags which are able to give more information allowing the correct media viewers etc to be loaded. However these are less widely supported and content may be specifically tailored to a particular platform or player. This option controls whether media content is enclosed in EMBED tags only or whether, where appropriate, it is additionally wrapped in OBJECT tags. Currently OBJECT tags are only used in a limited number of circumstances but they may become more widespread in the future. It is suggested that you leave this option on unless you encounter problems playing some content.", + type => $types{boolean}, + category => "web", + }, + { + name => "ZM_WEB_H_REFRESH_MAIN", + default => "300", + introduction => "There are now a number of options that are grouped into bandwidth categories, this allows you to configure the ZoneMinder client to work optimally over the various access methods you might to access the client.\n\nThe next few options control what happens when the client is running in 'high' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a local network or high speed link. In most cases the default values will be suitable as a starting point.", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_CYCLE", + default => "10", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_IMAGE", + default => "5", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_STATUS", + default => "3", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_REFRESH_EVENTS", + default => "30", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "highband", + }, + { + name => "ZM_WEB_H_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_BITRATE", + default => "150000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_VIDEO_MAXFPS", + default => "15", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_H_SCALE_THUMBS", + default => "no", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "highband", + }, + { + name => "ZM_WEB_H_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "highband", + }, + { + name => "ZM_WEB_H_AJAX_TIMEOUT", + default => "3000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "highband", + }, + { + name => "ZM_WEB_M_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + introduction => "The next few options control what happens when the client is running in 'medium' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a slower cable or DSL link. In most cases the default values will be suitable as a starting point.", + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_CYCLE", + default => "20", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_IMAGE", + default => "10", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_STATUS", + default => "5", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_REFRESH_EVENTS", + default => "60", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "medband", + }, + { + name => "ZM_WEB_M_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_BITRATE", + default => "75000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_VIDEO_MAXFPS", + default => "10", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_M_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "medband", + }, + { + name => "ZM_WEB_M_SHOW_PROGRESS", + default => "yes", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "medband", + }, + { + name => "ZM_WEB_M_AJAX_TIMEOUT", + default => "5000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "medband", + }, + { + name => "ZM_WEB_L_REFRESH_MAIN", + default => "300", + description => "How often (in seconds) the main console window should refresh itself", + introduction => "The next few options control what happens when the client is running in 'low' bandwidth mode. You should set these options for when accessing the ZoneMinder client over a modem or slow link. In most cases the default values will be suitable as a starting point.", + help => "The main console window lists a general status and the event totals for all monitors. This is not a trivial task and should not be repeated too frequently or it may affect the performance of the rest of the system.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_CYCLE", + default => "30", + description => "How often (in seconds) the cycle watch window swaps to the next monitor", + help => "The cycle watch window is a method of continuously cycling between images from all of your monitors. This option determines how often to refresh with a new image.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_IMAGE", + default => "15", + description => "How often (in seconds) the watched image is refreshed (if not streaming)", + help => "The live images from a monitor can be viewed in either streamed or stills mode. This option determines how often a stills image is refreshed, it has no effect if streaming is selected.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_STATUS", + default => "10", + description => "How often (in seconds) the status refreshes itself in the watch window", + help => "The monitor window is actually made from several frames. The one in the middle merely contains a monitor status which needs to refresh fairly frequently to give a true indication. This option determines that frequency.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_REFRESH_EVENTS", + default => "180", + description => "How often (in seconds) the event listing is refreshed in the watch window", + help => "The monitor window is actually made from several frames. The lower framme contains a listing of the last few events for easy access. This option determines how often this is refreshed.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "lowband", + }, + { + name => "ZM_WEB_L_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_BITRATE", + default => "25000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_L_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_EVENTS_VIEW", + default => "events", + description => "What the default view of multiple events should be.", + help => "Stored events can be viewed in either an events list format or in a timeline based one. This option sets the default view that will be used. Choosing one view here does not prevent the other view being used as it will always be selectable from whichever view is currently being used.", + type => { db_type=>"string", hint=>"events|timeline", pattern=>qr|^([lt])|i, format=>q( $1 =~ /^e/ ? "events" : "timeline" ) }, + category => "lowband", + }, + { + name => "ZM_WEB_L_SHOW_PROGRESS", + default => "no", + description => "Show the progress of replay in event view.", + help => "When viewing events an event navigation panel and progress bar is shown below the event itself. This allows you to jump to specific points in the event, but can can also dynamically update to display the current progress of the event replay itself. This progress is calculated from the actual event duration and is not directly linked to the replay itself, so on limited bandwidth connections may be out of step with the replay. This option allows you to turn off the progress display, whilst still keeping the navigation aspect, where bandwidth prevents it functioning effectively.", + type => $types{boolean}, + category => "lowband", + }, + { + name => "ZM_WEB_L_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "lowband", + }, + { + name => "ZM_WEB_P_CAN_STREAM", + default => "auto", + description => "Override the automatic detection of browser streaming capability", + help => "If you know that your browser can handle image streams of the type 'multipart/x-mixed-replace' but ZoneMinder does not detect this correctly you can set this option to ensure that the stream is delivered with or without the use of the Cambozola plugin. Selecting 'yes' will tell ZoneMinder that your browser can handle the streams natively, 'no' means that it can't and so the plugin will be used while 'auto' lets ZoneMinder decide.", + type => $types{tristate}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_STREAM_METHOD", + default => "jpeg", + description => "Which method should be used to send video streams to your browser.", + help => "ZoneMinder can be configured to use either mpeg encoded video or a series or still jpeg images when sending video streams. This option defines which is used. If you choose mpeg you should ensure that you have the appropriate plugins available on your browser whereas choosing jpeg will work natively on Mozilla and related browsers and with a Java applet on Internet Explorer", + type => { db_type=>"string", hint=>"mpeg|jpeg", pattern=>qr|^([mj])|i, format=>q( $1 =~ /^m/ ? "mpeg" : "jpeg" ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_SCALE", + default => "100", + description => "What the default scaling factor applied to 'live' or 'event' views is (%)", + help => "Normally ZoneMinder will display 'live' or 'event' streams in their native size. However if you have monitors with large dimensions or a slow link you may prefer to reduce this size, alternatively for small monitors you can enlarge it. This options lets you specify what the default scaling factor will be. It is expressed as a percentage so 100 is normal size, 200 is double size etc.", + type => { db_type=>"integer", hint=>"25|33|50|75|100|150|200|300|400", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_DEFAULT_RATE", + default => "100", + description => "What the default replay rate factor applied to 'event' views is (%)", + help => "Normally ZoneMinder will display 'event' streams at their native rate, i.e. as close to real-time as possible. However if you have long events it is often convenient to replay them at a faster rate for review. This option lets you specify what the default replay rate will be. It is expressed as a percentage so 100 is normal rate, 200 is double speed etc.", + type => { db_type=>"integer", hint=>"25|50|100|150|200|400|1000|2500|5000|10000", pattern=>qr|^(\d+)$|, format=>q( $1 ) }, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_BITRATE", + default => "8000", + description => "What the bitrate of the video encoded stream should be set to", + help => "When encoding real video via the ffmpeg library a bit rate can be specified which roughly corresponds to the available bandwidth used for the stream. This setting effectively corresponds to a 'quality' setting for the video. A low value will result in a blocky image whereas a high value will produce a clearer view. Note that this setting does not control the frame rate of the video however the quality of the video produced is affected both by this setting and the frame rate that the video is produced at. A higher frame rate at a particular bit rate result in individual frames being at a lower quality.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_VIDEO_MAXFPS", + default => "5", + description => "What the maximum frame rate for streamed video should be", + help => "When using streamed video the main control is the bitrate which determines how much data can be transmitted. However a lower bitrate at high frame rates results in a lower quality image. This option allows you to limit the maximum frame rate to ensure that video quality is maintained. An additional advantage is that encoding video at high frame rates is a processor intensive task when for the most part a very high frame rate offers little perceptible improvement over one that has a more manageable resource requirement. Note, this option is implemented as a cap beyond which binary reduction takes place. So if you have a device capturing at 15fps and set this option to 10fps then the video is not produced at 10fps, but rather at 7.5fps (15 divided by 2) as the final frame rate must be the original divided by a power of 2.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_SCALE_THUMBS", + default => "yes", + description => "Scale thumbnails in events, bandwidth versus cpu in rescaling", + help => "If unset, this option sends the whole image to the browser which resizes it in the window. If set the image is scaled down on the server before sending a reduced size image to the browser to conserve bandwidth at the cost of cpu on the server. Note that ZM can only perform the resizing if the appropriate PHP graphics functionality is installed. This is usually available in the php-gd package.", + type => $types{boolean}, + category => "phoneband", + }, + { + name => "ZM_WEB_P_AJAX_TIMEOUT", + default => "10000", + description => "How long to wait for Ajax request responses (ms)", + help => "The newer versions of the live feed and event views use Ajax to request information from the server and populate the views dynamically. This option allows you to specify a timeout if required after which requests are abandoned. A timeout may be necessary if requests would overwise hang such as on a slow connection. This would tend to consume a lot of browser memory and make the interface unresponsive. Ordinarily no requests should timeout so this setting should be set to a value greater than the slowest expected response. This value is in milliseconds but if set to zero then no timeout will be used.", + type => $types{integer}, + category => "phoneband", + }, + { + name => "ZM_DYN_LAST_VERSION", + default => "", + description => "What the last version of ZoneMinder recorded from zoneminder.com is", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_CURR_VERSION", + default => "@VERSION@", + description => "What the effective current version of ZoneMinder is, might be different from actual if versions ignored", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DB_VERSION", + default => "@VERSION@", + description => "What the version of the database is, from zmupdate", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_LAST_CHECK", + default => "", + description => "When the last check for version from zoneminder.com was", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_NEXT_REMINDER", + default => "", + description => "When the earliest time to remind about versions will be", + help => "", + type => $types{string}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_DONATE_REMINDER_TIME", + default => 0, + description => "When the earliest time to remind about donations will be", + help => "", + type => $types{integer}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_DYN_SHOW_DONATE_REMINDER", + default => "yes", + description => "Remind about donations or not", + help => "", + type => $types{boolean}, + readonly => 1, + category => "dynamic", + }, + { + name => "ZM_EYEZM_DEBUG", + default => "no", + description => "Switch additional debugging on for eyeZm Plugin", + help => "Enable or Disable extra debugging from the eyeZm Plugin. Extra debugging information will be displayed in it's own file (EYEZM_LOG_TO_FILE is set), or your Apache error log", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_TO_FILE", + default => "yes", + description => "When eyeZm Debugging is enabled, enabling this logs output to it's own file", + help => "When EYEZM_DEBUG is on and EYEZM_LOG_TO_FILE is on, output generated from the eyeZm Plugin will go to it's own file. Otherwise it will go to the apache error log.", + type => $types{boolean}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_LOG_FILE", + default => "@ZM_LOGDIR@/zm_xml.log", + description => "Default filename to use when logging eyeZm Output and EYEZM_LOG_TO_FILE is enabled", + help => "This file will contain it's own output from the eyeZm Plugin when EYEZM_LOG_TO_FILE and EYEZM_DEBUG are both enabled", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_EVENT_VCODEC", + default => "mpeg4", + description => "Default video-codec to use for encoding events", + help => "The eyeZm Plugin calls FFMPEG externally to encode the captured images. If your FFMPEG is not built with support for H264, change this to MPEG-4. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+).", + type => { db_type=>"string", hint=>"mpeg4|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mpeg4" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_FEED_VCODEC", + default => "mjpeg", + description => "Default video-codec to use for streaming the live feed", + help => "Determines whether the live stream is generated using native MJPEG streaming with ZoneMinder, or H264 using FFMPEG and HTML-5 streaming. If using H264, please check http://www.eyezm.com for H264 requirements and that your eyeZm version supports H264 (v1.2+). This is just a default parameter, and can be overridden with eyeZm.", + type => { db_type=>"string", hint=>"mjpeg|h264", pattern=>qr|^([mh])|i, format=>q( $1 =~ /^m/ ? "mjpeg" : "h264" ) }, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_BR", + default => "96k", + description => "Default bit-rate to use with FFMPEG for H264 streaming", + help => "When using the eyeZm Plugin to stream H264 data, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_DEFAULT_EVBR", + default => "128k", + description => "Default bit-rate to use with FFMPEG for H264 event viewing", + help => "When using the eyeZm Plugin to view events in H264, FFMPEG requires a bitrate to control the quality and bandwidth of the video. This should be specified in a format acceptable to FFMPEG. The default value is sufficient for most installations. This is just a default parameter, and can be overridden with eyeZm.", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_H264_TIMEOUT", + default => "20", + description => "Timeout (sec) to wait for H264 stream to start before terminating", + help => "The eyeZm Plugin will attempt to spawn an H264 stream when requested, and require that it complete within the timeout specified. If you have a slow system or find through the logs that the H264 stream is not starting because the timeout is expiring, even though FFMPEG is running, try increasing this value. If you have a fast system, decreasing this value can improve the responsiveness when there are issues starting H264 streams", + type => $types{string}, + category => "eyeZm", + }, + { + name => "ZM_EYEZM_SEG_DURATION", + default => "3", + description => "Segment duration used for streaming using HTTP-5 Streaming protocol", + help => "The HTTP-5 Live Streaming Protocol segments the input video stream into small chunks of a duration specified by this parameter. Increasing the segment duration will help with choppy connections on the other end, but will increase the latency in starting a stream.", + type => $types{string}, + category => "eyeZm", + }, +); + +our %options_hash = map { ( $_->{name}, $_ ) } @options; + +# This function should never need to be called explicitly, except if +# this module is 'require'd rather than 'use'd. See zmconfgen.pl. +sub initialiseConfig +{ + return if ( $configInitialised ); + + # Do some initial data munging to finish the data structures + # Create option ids + my $option_id = 0; + foreach my $option ( @options ) + { + if ( defined($option->{default}) ) + { + $option->{value} = $option->{default} + } + else + { + $option->{value} = ''; + } + #next if ( $option->{category} eq 'hidden' ); + $option->{id} = $option_id++; + } + $configInitialised = 1; +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::ConfigData - ZoneMinder Configuration Data module + +=head1 SYNOPSIS + + use ZoneMinder::ConfigData; + use ZoneMinder::ConfigData qw(:all); + + loadConfigFromDB(); + saveConfigToDB(); + +=head1 DESCRIPTION + +The ZoneMinder:ConfigData module contains the master definition of the ZoneMinder configuration options as well as helper methods. This module is intended for specialist confguration management and would not normally be used by end users. + +The configuration held in this module, which was previously in zmconfig.pl, includes the name, default value, description, help text, type and category for each option, as well as a number of additional fields in a small number of cases. + +=head1 METHODS + +=over 4 + +=item loadConfigFromDB (); + +Loads existing configuration from the database (if any) and merges it with the definitions held in this module. This results in the merging of any new configuration and the removal of any deprecated configuration while preserving the existing values of every else. + +=item saveConfigToDB (); + +Saves configuration held in memory to the database. The act of loading and saving configuration is a convenient way to ensure that the configuration held in the database corresponds with the most recent definitions and that all components are using the same set of configuration. + +=head2 EXPORT + +None by default. +The :data tag will export the various configuration data structures +The :functions tag will export the helper functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm new file mode 100644 index 000000000..2a646772d --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control.pm @@ -0,0 +1,205 @@ +# ========================================================================== +# +# ZoneMinder Base Control 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 base class definitions for the camera control +# protocol implementations +# +package ZoneMinder::Control; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Database qw(:all); + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my $id = shift; + my $self = {}; + $self->{name} = "PelcoD"; + if ( !defined($id) ) + { + Fatal( "No monitor defined when invoking protocol ".$self->{name} ); + } + $self->{id} = $id; + bless( $self, $class ); + return $self; +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + croak( "Can't access $name member of object of class $class" ); +} + +sub getKey() +{ + my $self = shift; + return( $self->{id} ); +} + +sub open +{ + my $self = shift; + Fatal( "No open method defined for protocol ".$self->{name} ); +} + +sub close +{ + my $self = shift; + Fatal( "No close method defined for protocol ".$self->{name} ); +} + +sub loadMonitor +{ + my $self = shift; + if ( !$self->{Monitor} ) + { + if ( !($self->{Monitor} = zmDbGetMonitor( $self->{id} )) ) + { + Fatal( "Monitor id ".$self->{id}." not found or not controllable" ); + } + if ( defined($self->{Monitor}->{AutoStopTimeout}) ) + { + # Convert to microseconds. + $self->{Monitor}->{AutoStopTimeout} = int(1000000*$self->{Monitor}->{AutoStopTimeout}); + } + } +} + +sub getParam +{ + my $self = shift; + my $params = shift; + my $name = shift; + my $default = shift; + + if ( defined($params->{$name}) ) + { + return( $params->{$name} ); + } + elsif ( defined($default) ) + { + return( $default ); + } + Fatal( "Missing mandatory parameter '$name'" ); +} + +sub executeCommand +{ + my $self = shift; + my $params = shift; + + $self->loadMonitor(); + + my $command = $params->{command}; + delete $params->{command}; + + #if ( !defined($self->{$command}) ) + #{ + #Fatal( "Unsupported command '$command'" ); + #} + &{$self->{$command}}( $self, $params ); +} + +sub printMsg() +{ + my $self = shift; + Fatal( "No printMsg method defined for protocol ".$self->{name} ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm new file mode 100644 index 000000000..e5a5882b9 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/AxisV2.pm @@ -0,0 +1,475 @@ +# ========================================================================== +# +# ZoneMinder Axis version 2 API Control Protocol 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 implementation of the Axis V2 API camera control +# protocol +# +package ZoneMinder::Control::AxisV2; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Axis V2 Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + #print( "http://$address/$cmd\n" ); + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "/axis-cgi/admin/restart.cgi"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=up"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=down"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=left"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=right"; + $self->sendCmd( $cmd ); +} + +sub moveConUpRight +{ + my $self = shift; + Debug( "Move Up/Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=upright"; + $self->sendCmd( $cmd ); +} + +sub moveConUpLeft +{ + my $self = shift; + Debug( "Move Up/Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=upleft"; + $self->sendCmd( $cmd ); +} + +sub moveConDownRight +{ + my $self = shift; + Debug( "Move Down/Right" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=downright"; + $self->sendCmd( $cmd ); +} + +sub moveConDownLeft +{ + my $self = shift; + Debug( "Move Down/Left" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=downleft"; + $self->sendCmd( $cmd ); +} + +sub moveMap +{ + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam( $params, 'xcoord' ); + my $ycoord = $self->getParam( $params, 'ycoord' ); + Debug( "Move Map to $xcoord,$ycoord" ); + my $cmd = "/axis-cgi/com/ptz.cgi?center=$xcoord,$ycoord&imagewidth=".$self->{Monitor}->{Width}."&imageheight=".$self->{Monitor}->{Height}; + $self->sendCmd( $cmd ); +} + +sub moveRelUp +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelDown +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rtilt=-$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelLeft +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + Debug( "Step Left $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelRight +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + Debug( "Step Right $step" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$step"; + $self->sendCmd( $cmd ); +} + +sub moveRelUpRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up/Right $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelUpLeft +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Up/Left $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelDownRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down/Right $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=$panstep&rtilt=-$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub moveRelDownLeft +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + Debug( "Step Down/Left $tiltstep/$panstep" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rpan=-$panstep&rtilt=-$tiltstep"; + $self->sendCmd( $cmd ); +} + +sub zoomRelTele +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Tele" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=$step"; + $self->sendCmd( $cmd ); +} + +sub zoomRelWide +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Wide" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rzoom=-$step"; + $self->sendCmd( $cmd ); +} + +sub focusRelNear +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Near" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=-$step"; + $self->sendCmd( $cmd ); +} + +sub focusRelFar +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Far" ); + my $cmd = "/axis-cgi/com/ptz.cgi?rfocus=$step"; + $self->sendCmd( $cmd ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=on"; + $self->sendCmd( $cmd ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off"; + $self->sendCmd( $cmd ); +} + +sub irisRelOpen +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Iris Open" ); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=$step"; + $self->sendCmd( $cmd ); +} + +sub irisRelClose +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Iris Close" ); + my $cmd = "/axis-cgi/com/ptz.cgi?riris=-$step"; + $self->sendCmd( $cmd ); +} + +sub irisAuto +{ + my $self = shift; + Debug( "Iris Auto" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=on"; + $self->sendCmd( $cmd ); +} + +sub irisMan +{ + my $self = shift; + Debug( "Iris Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autoiris=off"; + $self->sendCmd( $cmd ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Clear Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?removeserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Set Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?setserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Goto Preset $preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?gotoserverpresetno=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "/axis-cgi/com/ptz.cgi?move=home"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm new file mode 100644 index 000000000..358aecb2b --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Ncs370.pm @@ -0,0 +1,241 @@ +# ========================================================================== +# +# ZoneMinder Neu-Fusion Control Protocol 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 implementation of the Neu-Fusion NCS370 IP camera +# control protocol +# +package ZoneMinder::Control::Ncs370; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Ncs370 IP Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( POST=>"http://".$self->{Monitor}->{ControlAddress}."/PANTILTCONTROL.CGI" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=1"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=7"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=3"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=5"; + $self->sendCmd( $cmd ); +} + +sub moveConUpRight +{ + moveConUp(); + moveConRight(); +} + +sub moveConUpLeft +{ + moveConUp(); + moveConLeft(); +} + +sub moveConDownRight +{ + moveConDown(); + moveConRight(); +} + +sub moveConDownLeft +{ + moveConDown(); + moveConLeft(); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "PanSingleMoveDegree=1\nTiltSingleMoveDegree=1\nPanTiltSingleMove=4"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm new file mode 100644 index 000000000..643765e9f --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PanasonicIP.pm @@ -0,0 +1,322 @@ +# ========================================================================== +# +# ZoneMinder Panasonic IP Control Protocol 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 implementation of the Panasonic IP camera control +# protocol +# +package ZoneMinder::Control::PanasonicIP; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Panasonic IP Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "nphRestart?PAGE=Restart&Restart=OK"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "nphControlCamera?Direction=TiltUp"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "nphControlCamera?Direction=TiltDown"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "nphControlCamera?Direction=PanLeft"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "nphControlCamera?Direction=PanRight"; + $self->sendCmd( $cmd ); +} + +sub moveMap +{ + my $self = shift; + my $params = shift; + my $xcoord = $self->getParam( $params, 'xcoord' ); + my $ycoord = $self->getParam( $params, 'ycoord' ); + Debug( "Move Map to $xcoord,$ycoord" ); + my $cmd = "nphControlCamera?Direction=Direct&NewPosition.x=$xcoord&NewPosition.y=$ycoord&Width=".$self->{Monitor}->{Width}."&Height=".$self->{Monitor}->{Height}; + $self->sendCmd( $cmd ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Tele" ); + my $cmd = "nphControlCamera?Direction=ZoomTele"; + $self->sendCmd( $cmd ); +} + +sub zoomConWide +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Zoom Wide" ); + my $cmd = "nphControlCamera?Direction=ZoomWide"; + $self->sendCmd( $cmd ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Near" ); + my $cmd = "nphControlCamera?Direction=FocusNear"; + $self->sendCmd( $cmd ); +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'step' ); + Debug( "Focus Far" ); + my $cmd = "nphControlCamera?Direction=FocusFar"; + $self->sendCmd( $cmd ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my $cmd = "nphControlCamera?Direction=FocusAuto"; + $self->sendCmd( $cmd ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Manual" ); + my $cmd = "/axis-cgi/com/ptz.cgi?autofocus=off"; + $self->sendCmd( $cmd ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Clear Preset $preset" ); + my $cmd = "nphPresetNameCheck?Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Set Preset $preset" ); + my $cmd = "nphPresetNameCheck?PresetName=$preset&Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset' ); + Debug( "Goto Preset $preset" ); + my $cmd = "nphControlCamera?Direction=Preset&PresetOperation=Move&Data=$preset"; + $self->sendCmd( $cmd ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my $cmd = "nphControlCamera?Direction=HomePosition"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm new file mode 100644 index 000000000..6c507bd1a --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoD.pm @@ -0,0 +1,735 @@ +# ========================================================================== +# +# ZoneMinder Pelco-D Control Protocol 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 implementation of the Pelco-D camera control +# protocol +# +package ZoneMinder::Control::PelcoD; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Pelco-D Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use constant SYNC => 0xff; +use constant COMMAND_GAP => 100000; # In ms + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use Device::SerialPort; + $self->{port} = new Device::SerialPort( $self->{Monitor}->{ControlDevice} ); + $self->{port}->baudrate(2400); + $self->{port}->databits(8); + $self->{port}->parity('none'); + $self->{port}->stopbits(1); + $self->{port}->handshake('none'); + + $self->{port}->read_const_time(50); + $self->{port}->read_char_time(10); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; + $self->{port}->close(); +} + +sub printMsg +{ + if ( logDebugging() ) + { + my $self = shift; + my $msg = shift; + my $prefix = shift || ""; + $prefix = $prefix.": " if ( $prefix ); + + my $line_length = 16; + my $msg_len = int(@$msg); + + my $msg_str = $prefix; + for ( my $i = 0; $i < $msg_len; $i++ ) + { + if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) ) + { + $msg_str .= sprintf( "\n%*s", length($prefix), "" ); + } + $msg_str .= sprintf( "%02x ", $msg->[$i] ); + } + $msg_str .= "[".$msg_len."]"; + Debug( $msg_str ); + } +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $ack = shift || 0; + + my $result = undef; + + my $checksum = 0x00; + for ( my $i = 1; $i < int(@$cmd); $i++ ) + { + $checksum += $cmd->[$i]; + $checksum &= 0xff; + } + push( @$cmd, $checksum ); + + $self->printMsg( $cmd, "Tx" ); + my $id = $cmd->[0] & 0xf; + + my $tx_msg = pack( "C*", @$cmd ); + + #print( "Tx: ".length( $tx_msg )." bytes\n" ); + my $n_bytes = $self->{port}->write( $tx_msg ); + if ( !$n_bytes ) + { + Error( "Write failed: $!" ); + } + if ( $n_bytes != length($tx_msg) ) + { + Error( "Incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" ); + } + + if ( $ack ) + { + Debug( "Waiting for ack" ); + my $max_wait = 3; + my $now = time(); + while( 1 ) + { + my ( $count, $rx_msg ) = $self->{port}->read(4); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x40 ) + { + my $socket = $resp[1] & 0x0f; + Debug( "Got ack for socket $socket" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + Warning( "Response timeout" ); + last; + } + } + } +} + +sub remoteReset +{ + my $self = shift; + Debug( "Remote Reset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0f, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub resetDefaults +{ + my $self = shift; + Debug( "Reset Defaults" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x29, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub cameraOff +{ + my $self = shift; + Debug( "Camera Off" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x08, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub cameraOn +{ + my $self = shift; + Debug( "Camera On" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x88, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub autoScan +{ + my $self = shift; + Debug( "Auto Scan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x90, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub manScan +{ + my $self = shift; + Debug( "Manual Scan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x10, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub stop +{ + my $self = shift; + Debug( "Stop" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub moveConUp +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x08, 0x00, $speed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConDown +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x10, 0x00, $speed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConLeft +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x04, $speed, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConRight +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x02, $speed, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0c, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x0a, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Left" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x14, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Right" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x12, $panspeed, $tiltspeed ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveStop +{ + my $self = shift; + Debug( "Move Stop" ); + $self->stop(); +} + +sub flip180 +{ + my $self = shift; + Debug( "Flip 180" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x21 ); + $self->sendCmd( \@msg ); +} + +sub zeroPan +{ + my $self = shift; + Debug( "Zero Pan" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22 ); + $self->sendCmd( \@msg ); +} + +sub _setZoomSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Zoom Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x25, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub zoomStop +{ + my $self = shift; + Debug( "Zoom Stop" ); + $self->stop(); + $self->_setZoomSpeed( 0 ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Tele" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x20, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomConWide +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Wide" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x40, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub _setFocusSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Focus Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Near" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x01, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Far" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x80, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusStop +{ + my $self = shift; + Debug( "Focus Stop" ); + $self->stop(); + $self->_setFocusSpeed( 0 ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Man" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x02 ); + $self->sendCmd( \@msg ); +} + +sub _setIrisSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Iris Speed $speed" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed ); + $self->sendCmd( \@msg ); +} + +sub irisConClose +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Close" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x04, 0x00, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisConOpen +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Open" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x02, 0x80, 0x00, 0x00 ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisStop +{ + my $self = shift; + Debug( "Iris Stop" ); + $self->stop(); + $self->_setIrisSpeed( 0 ); +} + +sub irisAuto +{ + my $self = shift; + Debug( "Iris Auto" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub irisMan +{ + my $self = shift; + Debug( "Iris Man" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x02 ); + $self->sendCmd( \@msg ); +} + +sub writeScreen +{ + my $self = shift; + my $params = shift; + my $string = $self->getParam( $params, 'string' ); + Debug( "Writing '$string' to screen" ); + + my @chars = unpack( "C*", $string ); + for ( my $i = 0; $i < length($string); $i++ ) + { + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x15, $i, $chars[$i] ); + $self->sendCmd( \@msg ); + usleep( COMMAND_GAP ); + } +} + +sub clearScreen +{ + my $self = shift; + Debug( "Clear Screen" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x17, 0x00, 0x00 ); + $self->sendCmd( \@msg ); +} + +sub clearPreset +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Clear Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x05, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Set Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x03, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Goto Preset $preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, $preset ); + $self->sendCmd( \@msg ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my @msg = ( SYNC, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22 ); + $self->sendCmd( \@msg ); +} + +sub reset +{ + my $self = shift; + Debug( "Reset" ); + $self->remoteReset(); + $self->resetDefaults(); +} + +sub wake +{ + my $self = shift; + Debug( "Wake" ); + $self->cameraOn(); +} + +sub sleep +{ + my $self = shift; + Debug( "Sleep" ); + $self->cameraOff(); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm new file mode 100644 index 000000000..c743f2b51 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/PelcoP.pm @@ -0,0 +1,736 @@ +# ========================================================================== +# +# ZoneMinder Pelco-P Control Protocol 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 implementation of the Pelco-P camera control +# protocol +# +package ZoneMinder::Control::PelcoD; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Pelco-P Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use constant STX => 0xa0; +use constant ETX => 0xaf; +use constant COMMAND_GAP => 100000; # In ms + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use Device::SerialPort; + $self->{port} = new Device::SerialPort( $self->{Monitor}->{ControlDevice} ); + $self->{port}->baudrate(4800); + $self->{port}->databits(8); + $self->{port}->parity('none'); + $self->{port}->stopbits(1); + $self->{port}->handshake('none'); + + $self->{port}->read_const_time(50); + $self->{port}->read_char_time(10); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; + $self->{port}->close(); +} + +sub printMsg +{ + if ( logDebugging() ) + { + my $self = shift; + my $msg = shift; + my $prefix = shift || ""; + $prefix = $prefix.": " if ( $prefix ); + + my $line_length = 16; + my $msg_len = int(@$msg); + + my $msg_str = $prefix; + for ( my $i = 0; $i < $msg_len; $i++ ) + { + if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) ) + { + $msg_str .= sprintf( "\n%*s", length($prefix), "" ); + } + $msg_str .= sprintf( "%02x ", $msg->[$i] ); + } + $msg_str .= "[".$msg_len."]"; + Debug( $msg_str ); + } +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $ack = shift || 0; + + my $result = undef; + + my $checksum = 0x00; + for ( my $i = 1; $i < int(@$cmd); $i++ ) + { + $checksum ^= $cmd->[$i]; + } + $checksum &= 0xff; + push( @$cmd, $checksum ); + + $self->printMsg( $cmd, "Tx" ); + my $id = $cmd->[0] & 0xf; + + my $tx_msg = pack( "C*", @$cmd ); + + #print( "Tx: ".length( $tx_msg )." bytes\n" ); + my $n_bytes = $self->{port}->write( $tx_msg ); + if ( !$n_bytes ) + { + Error( "Write failed: $!" ); + } + if ( $n_bytes != length($tx_msg) ) + { + Error( "Incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" ); + } + + if ( $ack ) + { + Debug( "Waiting for ack" ); + my $max_wait = 3; + my $now = time(); + while( 1 ) + { + my ( $count, $rx_msg ) = $self->{port}->read(4); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x40 ) + { + my $socket = $resp[1] & 0x0f; + Debug( "Got ack for socket $socket" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + Warning( "Response timeout" ); + last; + } + } + } +} + +sub remoteReset +{ + my $self = shift; + Debug( "Remote Reset" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x0f, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub resetDefaults +{ + my $self = shift; + Debug( "Reset Defaults" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x29, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub cameraOff +{ + my $self = shift; + Debug( "Camera Off" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x08, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub cameraOn +{ + my $self = shift; + Debug( "Camera On" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x88, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub autoScan +{ + my $self = shift; + Debug( "Auto Scan" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x90, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub manScan +{ + my $self = shift; + Debug( "Manual Scan" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x10, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub stop +{ + my $self = shift; + Debug( "Stop" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub moveConUp +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x08, 0x00, $speed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConDown +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x10, 0x00, $speed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConLeft +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Left" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x04, $speed, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConRight +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed' ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Right" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x02, $speed, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Left" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x0c, $panspeed, $tiltspeed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConUpRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Right" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x0a, $panspeed, $tiltspeed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Left" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x14, $panspeed, $tiltspeed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveConDownRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x3f ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x3f ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Right" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x12, $panspeed, $tiltspeed, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop(); + } +} + +sub moveStop +{ + my $self = shift; + Debug( "Move Stop" ); + $self->stop(); +} + +sub flip180 +{ + my $self = shift; + Debug( "Flip 180" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x21, ETX ); + $self->sendCmd( \@msg ); +} + +sub zeroPan +{ + my $self = shift; + Debug( "Zero Pan" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22, ETX ); + $self->sendCmd( \@msg ); +} + +sub _setZoomSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Zoom Speed $speed" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x25, 0x00, $speed, ETX ); + $self->sendCmd( \@msg ); +} + +sub zoomStop +{ + my $self = shift; + Debug( "Zoom Stop" ); + $self->stop(); + $self->_setZoomSpeed( 0 ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Tele" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x20, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomConWide +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x01 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Wide" ); + $self->_setZoomSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x40, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub _setFocusSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Focus Speed $speed" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed, ETX ); + $self->sendCmd( \@msg ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Near" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x01, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x03 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Focus Far" ); + $self->_setFocusSpeed( $speed ); + usleep( COMMAND_GAP ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x80, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setFocusSpeed( 0 ); + } +} + +sub focusStop +{ + my $self = shift; + Debug( "Focus Stop" ); + $self->stop(); + $self->_setFocusSpeed( 0 ); +} + +sub focusAuto +{ + my $self = shift; + Debug( "Focus Auto" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub focusMan +{ + my $self = shift; + Debug( "Focus Man" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x2b, 0x00, 0x02, ETX ); + $self->sendCmd( \@msg ); +} + +sub _setIrisSpeed +{ + my $self = shift; + my $speed = shift; + Debug( "Set Iris Speed $speed" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x27, 0x00, $speed, ETX ); + $self->sendCmd( \@msg ); +} + +sub irisConClose +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Close" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x04, 0x00, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisConOpen +{ + my $self = shift; + my $params = shift; + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Iris Open" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x02, 0x80, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->_setIrisSpeed( 0 ); + } +} + +sub irisStop +{ + my $self = shift; + Debug( "Iris Stop" ); + $self->stop(); + $self->_setIrisSpeed( 0 ); +} + +sub irisAuto +{ + my $self = shift; + Debug( "Iris Auto" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub irisMan +{ + my $self = shift; + Debug( "Iris Man" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x2d, 0x00, 0x02, ETX ); + $self->sendCmd( \@msg ); +} + +sub writeScreen +{ + my $self = shift; + my $params = shift; + my $string = $self->getParam( $params, 'string' ); + Debug( "Writing '$string' to screen" ); + + my @chars = unpack( "C*", $string ); + for ( my $i = 0; $i < length($string); $i++ ) + { + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x15, $i, $chars[$i], ETX ); + $self->sendCmd( \@msg ); + usleep( COMMAND_GAP ); + } +} + +sub clearScreen +{ + my $self = shift; + Debug( "Clear Screen" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x17, 0x00, 0x00, ETX ); + $self->sendCmd( \@msg ); +} + +sub clearPreset +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Clear Preset $preset" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x05, 0x00, $preset, ETX ); + $self->sendCmd( \@msg ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Set Preset $preset" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x03, 0x00, $preset, ETX ); + $self->sendCmd( \@msg ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Goto Preset $preset" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, $preset, ETX ); + $self->sendCmd( \@msg ); +} + +sub presetHome +{ + my $self = shift; + Debug( "Home Preset" ); + my @msg = ( STX, $self->{Monitor}->{ControlAddress}, 0x00, 0x07, 0x00, 0x22, ETX ); + $self->sendCmd( \@msg ); +} + +sub reset +{ + my $self = shift; + Debug( "Reset" ); + $self->remoteReset(); + $self->resetDefaults(); +} + +sub wake +{ + my $self = shift; + Debug( "Wake" ); + $self->cameraOn(); +} + +sub sleep +{ + my $self = shift; + Debug( "Sleep" ); + $self->cameraOff(); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/Visca.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/Visca.pm new file mode 100644 index 000000000..37f30dc09 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/Visca.pm @@ -0,0 +1,668 @@ +# ========================================================================== +# +# ZoneMinder Visca Control Protocol 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 implementation of the Visca camera control +# protocol +# +package ZoneMinder::Control::Visca; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Visca Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Time::HiRes qw( usleep ); + +use constant SYNC => 0xff; +use constant COMMAND_GAP => 100000; # In ms + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + + use Device::SerialPort; + $self->{port} = new Device::SerialPort( $self->{Monitor}->{ControlDevice} ); + $self->{port}->baudrate(9600); + $self->{port}->databits(8); + $self->{port}->parity('none'); + $self->{port}->stopbits(1); + $self->{port}->handshake('rts'); + $self->{port}->stty_echo(0); + + #$self->{port}->read_const_time(250); + $self->{port}->read_char_time(2); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; + $self->{port}->close(); +} + +sub printMsg +{ + if ( logDebugging() ) + { + my $self = shift; + my $msg = shift; + my $prefix = shift || ""; + $prefix = $prefix.": " if ( $prefix ); + + my $line_length = 16; + my $msg_len = int(@$msg); + + my $msg_str = $prefix; + for ( my $i = 0; $i < $msg_len; $i++ ) + { + if ( ($i > 0) && ($i%$line_length == 0) && ($i != ($msg_len-1)) ) + { + $msg_str .= sprintf( "\n%*s", length($prefix), "" ); + } + $msg_str .= sprintf( "%02x ", $msg->[$i] ); + } + $msg_str .= "[".$msg_len."]"; + Debug( $msg_str ); + } +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + my $ack = shift || 0; + my $cmp = shift || 0; + + my $result = undef; + + $self->printMsg( $cmd, "Tx" ); + my $id = $cmd->[0] & 0xf; + + my $tx_msg = pack( "C*", @$cmd ); + + #print( "Tx: ".length( $tx_msg )." bytes\n" ); + my $n_bytes = $self->{port}->write( $tx_msg ); + if ( !$n_bytes ) + { + Error( "Write failed: $!" ); + } + if ( $n_bytes != length($tx_msg) ) + { + Error( "Incomplete write, only ".$n_bytes." of ".length($tx_msg)." written: $!" ); + } + + if ( $ack ) + { + Debug( "Waiting for ack" ); + my $max_wait = 3; + my $now = time(); + while( 1 ) + { + my ( $count, $rx_msg ) = $self->{port}->read(4); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + $self->printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x40 ) + { + my $socket = $resp[1] & 0x0f; + Debug( "Got ack for socket $socket" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + last; + } + } + } + + if ( $cmp ) + { + Debug( "Waiting for command complete" ); + my $max_wait = 10; + my $now = time(); + while( 1 ) + { + #print( "Waiting\n" ); + my ( $count, $rx_msg ) = $self->{port}->read(16); + + if ( $count ) + { + #print( "Rx1: ".$count." bytes\n" ); + my @resp = unpack( "C*", $rx_msg ); + $self->printMsg( \@resp, "Rx" ); + + if ( $resp[0] = 0x80 + ($id<<4) ) + { + if ( ($resp[1] & 0xf0) == 0x50 ) + { + Debug( "Got command complete" ); + $result = !undef; + } + else + { + Error( "Got bogus response" ); + } + last; + } + else + { + Error( "Got message for camera ".(($resp[0]-0x80)>>4) ); + } + } + if ( (time() - $now) > $max_wait ) + { + last; + } + } + } + return( $result ); +} + +sub cameraOff +{ + my $self = shift; + Debug( "Camera Off\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x00, 0x0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub cameraOn +{ + my $self = shift; + Debug( "Camera On\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x00, 0x2, SYNC ); + $self->sendCmd( \@msg ); +} + +sub stop +{ + my $self = shift; + Debug( "Stop\n" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, 0x00, 0x03, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveConUp +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConDown +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, 0x00, $speed, 0x03, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub movConLeft +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $speed, 0x00, 0x01, 0x03, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveConRight +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $speed, 0x00, 0x02, 0x03, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveUpLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveUpRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Up/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x01, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveDownLeft +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x01, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveDownRight +{ + my $self = shift; + my $params = shift; + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Move Down/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x01, $panspeed, $tiltspeed, 0x02, 0x02, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->stop( $params ); + } +} + +sub moveRelUp +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'tiltstep' ); + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, SYNC ); + + $self->sendCmd( \@msg ); +} + +sub moveRelDown +{ + my $self = shift; + my $params = shift; + my $step = -$self->getParam( $params, 'tiltstep' ); + my $speed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, 0x00, $speed, 0x00, 0x00, 0x00, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelLeft +{ + my $self = shift; + my $params = shift; + my $step = -$self->getParam( $params, 'panstep' ); + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + Debug( "Step Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelRight +{ + my $self = shift; + my $params = shift; + my $step = $self->getParam( $params, 'panstep' ); + my $speed = $self->getParam( $params, 'panspeed', 0x40 ); + Debug( "Step Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $speed, 0x00, ($step&0xf000)>>12, ($step&0x0f00)>>8, ($step&0x00f0)>>4, ($step&0x000f)>>0, 0x00, 0x00, 0x00, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelUpLeft +{ + my $self = shift; + my $params = shift; + my $panstep = -$self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelUpRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = $self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Up/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelDownLeft +{ + my $self = shift; + my $params = shift; + my $panstep = -$self->getParam( $params, 'panstep' ); + my $tiltstep = -$self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down/Left" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub moveRelDownRight +{ + my $self = shift; + my $params = shift; + my $panstep = $self->getParam( $params, 'panstep' ); + my $tiltstep = -$self->getParam( $params, 'tiltstep' ); + my $panspeed = $self->getParam( $params, 'panspeed', 0x40 ); + my $tiltspeed = $self->getParam( $params, 'tiltspeed', 0x40 ); + Debug( "Step Down/Right" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x03, $panspeed, $tiltspeed, ($panstep&0xf000)>>12, ($panstep&0x0f00)>>8, ($panstep&0x00f0)>>4, ($panstep&0x000f)>>0, ($tiltstep&0xf000)>>12, ($tiltstep&0x0f00)>>8, ($tiltstep&0x00f0)>>4, ($tiltstep&0x000f)>>0, SYNC ); + $self->sendCmd( \@msg ); +} + +sub zoomConTele +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x06 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Tele" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x20|$speed, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomWide +{ + my $self = shift; + my $params = shift; + my $speed = $self->getParam( $params, 'speed', 0x06 ); + my $autostop = $self->getParam( $params, 'autostop', 0 ); + Debug( "Zoom Wide" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x30|$speed, SYNC ); + $self->sendCmd( \@msg ); + if( $autostop && $self->{Monitor}->{AutoStopTimeout} ) + { + usleep( $self->{Monitor}->{AutoStopTimeout} ); + $self->zoomStop(); + } +} + +sub zoomStop +{ + my $self = shift; + my $params = shift; + Debug( "Zoom Stop" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x07, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusConNear +{ + my $self = shift; + my $params = shift; + Debug( "Focus Near" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusConFar +{ + my $self = shift; + my $params = shift; + Debug( "Focus Far" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x02, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusStop +{ + my $self = shift; + my $params = shift; + Debug( "Focus Stop" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x08, 0x00, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusAuto +{ + my $self = shift; + my $params = shift; + Debug( "Focus Auto" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x38, 0x02, SYNC ); + $self->sendCmd( \@msg ); +} + +sub focusMan +{ + my $self = shift; + my $params = shift; + Debug( "Focus Man" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x38, 0x03, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetClear +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Clear Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x00, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetSet +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Set Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x01, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetGoto +{ + my $self = shift; + my $params = shift; + my $preset = $self->getParam( $params, 'preset', 1 ); + Debug( "Goto Preset $preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x04, 0x3f, 0x02, $preset, SYNC ); + $self->sendCmd( \@msg ); +} + +sub presetHome +{ + my $self = shift; + my $params = shift; + Debug( "Home Preset" ); + my @msg = ( 0x80|$self->{Monitor}->{ControlAddress}, 0x01, 0x06, 0x04, SYNC ); + $self->sendCmd( \@msg ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm b/scripts/ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm new file mode 100644 index 000000000..33a15cba1 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Control/mjpgStreamer.pm @@ -0,0 +1,252 @@ +# ========================================================================== +# +# ZoneMinder mjpg STreamer Control Protocol Module, $Date: 2007-11-04 17:30:29 +0000 (Sun, 04 Nov 2007) $, $Revision: 2229 $ +# Copyright (C) 2003, 2004, 2005, 2006 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 implementation of the mjpg streamer camera control +# protocol +# +package ZoneMinder::Control::mjpgStreamer; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Control; + +our @ISA = qw(ZoneMinder::Control); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# mjpgSTreamer Control Protocol +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Time::HiRes qw( usleep ); + +sub new +{ + my $class = shift; + my $id = shift; + my $self = ZoneMinder::Control->new( $id ); + Debug( "Camera New" ); + bless( $self, $class ); + srand( time() ); + return $self; +} + +our $AUTOLOAD; + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + Debug( "Camera AUTOLOAD" ); + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + Fatal( "Can't access $name member of object of class $class" ); +} + +sub open +{ + my $self = shift; + + $self->loadMonitor(); + Debug( "Camera open" ); + use LWP::UserAgent; + $self->{ua} = LWP::UserAgent->new; + $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION ); + + $self->{state} = 'open'; +} + +sub close +{ + my $self = shift; + $self->{state} = 'closed'; +} + +sub printMsg +{ + my $self = shift; + my $msg = shift; + my $msg_len = length($msg); + + Debug( $msg."[".$msg_len."]" ); +} + +sub sendCmd +{ + my $self = shift; + my $cmd = shift; + + my $result = undef; + + printMsg( $cmd, "Tx" ); + + my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" ); + my $res = $self->{ua}->request($req); + + if ( $res->is_success ) + { + $result = !undef; + } + else + { + Error( "Error check failed: '".$res->status_line()."'" ); + } + + return( $result ); +} + +sub Up +{ + my $self = shift; + $self->moveConUp(); +} + +sub Down +{ + my $self = shift; + $self->moveConDown(); +} + +sub Left +{ + my $self = shift; + $self->moveConLeft(); +} + +sub Right +{ + my $self = shift; + $self->moveConRight(); +} + + +sub reset +{ + my $self = shift; + $self->cameraReset(); +} + + + +sub cameraReset +{ + my $self = shift; + Debug( "Camera Reset" ); + my $cmd = "?action=command&command=reset_pan_tilt"; + $self->sendCmd( $cmd ); +} + +sub moveConUp +{ + my $self = shift; + Debug( "Move Up" ); + my $cmd = "?action=command&command=tilt_minus"; + $self->sendCmd( $cmd ); +} + +sub moveConDown +{ + my $self = shift; + Debug( "Move Down" ); + my $cmd = "?action=command&command=tilt_plus"; + $self->sendCmd( $cmd ); +} + +sub moveConLeft +{ + my $self = shift; + Debug( "Move Left" ); + my $cmd = "?action=command&command=pan_plus"; + $self->sendCmd( $cmd ); +} + +sub moveConRight +{ + my $self = shift; + Debug( "Move Right" ); + my $cmd = "?action=command&command=pan_minus"; + $self->sendCmd( $cmd ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=head1 COPYRIGHT AND LICENSE + +Copyright (C) 2005 by 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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Database.pm b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm new file mode 100644 index 000000000..d0bae5dde --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Database.pm @@ -0,0 +1,238 @@ +# ========================================================================== +# +# ZoneMinder Database 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::Database; + +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( + zmDbConnect + zmDbDisconnect + zmDbGetMonitors + zmDbGetMonitor + zmDbGetMonitorAndControl + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Database Access +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use ZoneMinder::Config qw(:all); + +use Carp; + +our $dbh = undef; + +sub zmDbConnect( ;$ ) +{ + my $force = shift; + if ( $force ) + { + zmDbDisconnect(); + } + if ( !defined( $dbh ) ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + + if ( defined($port) ) + { + $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".$host.";port=".$port, ZM_DB_USER, ZM_DB_PASS ); + } + else + { + $dbh = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + } + $dbh->trace( 0 ); + } + return( $dbh ); +} + +sub zmDbDisconnect() +{ + if ( defined( $dbh ) ) + { + $dbh->disconnect(); + $dbh = undef; + } +} + +use constant DB_MON_ALL => 0; # All monitors +use constant DB_MON_CAPT => 1; # All monitors that are capturing +use constant DB_MON_ACTIVE => 2; # All monitors that are active +use constant DB_MON_MOTION => 3; # All monitors that are doing motion detection +use constant DB_MON_RECORD => 4; # All monitors that are doing unconditional recording +use constant DB_MON_PASSIVE => 5; # All monitors that are in nodect state + +sub zmDbGetMonitors( ;$ ) +{ + zmDbConnect(); + + my $function = shift || DB_MON_ALL; + my $sql = "select * from Monitors"; + + if ( $function ) + { + if ( $function == DB_MON_CAPT ) + { + $sql .= " where Function >= 'Monitor'"; + } + elsif ( $function == DB_MON_ACTIVE ) + { + $sql .= " where Function > 'Monitor'"; + } + elsif ( $function == DB_MON_MOTION ) + { + $sql .= " where Function = 'Modect' or Function = 'Mocord'"; + } + elsif ( $function == DB_MON_RECORD ) + { + $sql .= " where Function = 'Record' or Function = 'Mocord'"; + } + elsif ( $function == DB_MON_PASSIVE ) + { + $sql .= " where Function = 'Nodect'"; + } + } + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or croak( "Can't execute '$sql': ".$sth->errstr() ); + + my @monitors; + while( my $monitor = $sth->fetchrow_hashref() ) + { + push( @monitors, $monitor ); + } + $sth->finish(); + return( \@monitors ); +} + +sub zmDbGetMonitor( $ ) +{ + zmDbConnect(); + + my $id = shift; + + return( undef ) if ( !defined($id) ); + + my $sql = "select * from Monitors where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or croak( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $id ) or croak( "Can't execute '$sql': ".$sth->errstr() ); + my $monitor = $sth->fetchrow_hashref(); + + return( $monitor ); +} + +sub zmDbGetMonitorAndControl( $ ) +{ + zmDbConnect(); + + my $id = shift; + + return( undef ) if ( !defined($id) ); + + my $sql = "select C.*,M.*,C.Protocol from Monitors as M inner join Controls as C on (M.ControlId = C.Id) where M.Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $id ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + my $monitor = $sth->fetchrow_hashref(); + + return( $monitor ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/General.pm b/scripts/ZoneMinder/lib/ZoneMinder/General.pm new file mode 100644 index 000000000..5af7150a8 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/General.pm @@ -0,0 +1,768 @@ +# ========================================================================== +# +# ZoneMinder General Utility 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::General; + +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( + executeShellCommand + getCmdFormat + runCommand + setFileOwner + getEventPath + createEventPath + createEvent + deleteEventFiles + makePath + jsonEncode + jsonDecode + ) ] +); +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; + +# For running general shell commands +sub executeShellCommand( $ ) +{ + my $command = shift; + my $output = qx( $command ); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + Debug( "Command: $command\n" ); + chomp( $output ); + Debug( "Output: $output\n" ); + } + return( $status ); +} + +sub getCmdFormat() +{ + Debug( "Testing valid shell syntax\n" ); + + my ( $name ) = getpwuid( $> ); + if ( $name eq ZM_WEB_USER ) + { + Debug( "Running as '$name', su commands not needed\n" ); + return( "" ); + } + + my $null_command = "true"; + + my $prefix = "sudo -u ".ZM_WEB_USER." "; + my $suffix = ""; + my $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + $command .= " > /dev/null 2>&1"; + my $output = qx($command); + my $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + + $prefix = "su ".ZM_WEB_USER." --shell=/bin/sh --command='"; + $suffix = "'"; + $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + my $output = qx($command); + my $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + + $prefix = "su ".ZM_WEB_USER." -c '"; + $suffix = "'"; + $command = $prefix.$null_command.$suffix; + Debug( "Testing \"$command\"\n" ); + $output = qx($command); + $status = $? >> 8; + if ( !$status ) + { + Debug( "Test ok, using format \"$prefix$suffix\"\n" ); + return( $prefix, $suffix ); + } + else + { + chomp( $output ); + Debug( "Test failed, '$output'\n" ); + } + } + } + Error( "Unable to find valid 'su' syntax\n" ); + exit( -1 ); +} + +our $testedShellSyntax = 0; +our ( $cmdPrefix, $cmdSuffix ); + +# For running ZM daemons etc +sub runCommand( $ ) +{ + if ( !$testedShellSyntax ) + { + # Determine the appropriate syntax for the su command + ( $cmdPrefix, $cmdSuffix ) = getCmdFormat(); + $testedShellSyntax = !undef; + } + + my $command = shift; + $command = ZM_PATH_BIN."/".$command; + if ( $cmdPrefix ) + { + $command = $cmdPrefix.$command.$cmdSuffix; + } + Debug( "Command: $command\n" ); + my $output = qx($command); + my $status = $? >> 8; + chomp( $output ); + if ( $status || logDebugging() ) + { + if ( $status ) + { + Error( "Unable to run \"$command\", output is \"$output\"\n" ); + exit( -1 ); + } + else + { + Debug( "Output: $output\n" ); + } + } + return( $output ); +} + +sub getEventPath( $ ) +{ + my $event = shift; + + my $event_path = ""; + if ( ZM_USE_DEEP_STORAGE ) + { + $event_path = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.strftime( "%y/%m/%d/%H/%M/%S", localtime($event->{Time}) ); + } + else + { + $event_path = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id}; + } + $event_path = ZM_PATH_WEB.'/'.$event_path if ( index(ZM_DIR_EVENTS,'/') != 0 ); + return( $event_path ); +} + +sub createEventPath( $ ) +{ + # + # WARNING assumes running from events directory + # + my $event = shift; + my $eventRootPath = (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + my $eventPath = $eventRootPath.'/'.$event->{MonitorId}; + + if ( ZM_USE_DEEP_STORAGE ) + { + my @startTime = localtime( $event->{StartTime} ); + + my @datetimeParts = (); + $datetimeParts[0] = sprintf( "%02d", $startTime[5]-100 ); + $datetimeParts[1] = sprintf( "%02d", $startTime[4]+1 ); + $datetimeParts[2] = sprintf( "%02d", $startTime[3] ); + $datetimeParts[3] = sprintf( "%02d", $startTime[2] ); + $datetimeParts[4] = sprintf( "%02d", $startTime[1] ); + $datetimeParts[5] = sprintf( "%02d", $startTime[0] ); + + my $datePath = join('/',@datetimeParts[0..2]); + my $timePath = join('/',@datetimeParts[3..5]); + + makePath( $datePath, $eventPath ); + $eventPath .= '/'.$datePath; + + # Create event id symlink + my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + symlink( $timePath, $idFile ) or Fatal( "Can't symlink $idFile -> $eventPath: $!" ); + + makePath( $timePath, $eventPath ); + $eventPath .= '/'.$timePath; + setFileOwner( $idFile ); # Must come after directory has been created + + # Create empty id tag file + $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + open( ID_FP, ">$idFile" ) or Fatal( "Can't open $idFile: $!" ); + close( ID_FP ); + setFileOwner( $idFile ); + } + else + { + makePath( $event->{Id}, $eventPath ); + $eventPath .= '/'.$event->{Id}; + + my $idFile = sprintf( "%s/.%d", $eventPath, $event->{Id} ); + open( ID_FP, ">$idFile" ) or Fatal( "Can't open $idFile: $!" ); + close( ID_FP ); + setFileOwner( $idFile ); + } + return( $eventPath ); +} + +use Data::Dumper; + +our $_setFileOwner = undef; +our ( $_ownerUid, $_ownerGid ); + +sub _checkProcessOwner() +{ + if ( !defined($_setFileOwner) ) + { + my ( $processOwner ) = getpwuid( $> ); + if ( $processOwner ne ZM_WEB_USER ) + { + # Not running as web user, so should be root in whch case chown the temporary directory + ( my $ownerName, my $ownerPass, $_ownerUid, $_ownerGid ) = getpwnam( ZM_WEB_USER ) or Fatal( "Can't get user details for web user '".ZM_WEB_USER."': $!" ); + $_setFileOwner = 1; + } + else + { + $_setFileOwner = 0; + } + } + return( $_setFileOwner ); +} + +sub setFileOwner( $ ) +{ + my $file = shift; + + if ( _checkProcessOwner() ) + { + chown( $_ownerUid, $_ownerGid, $file ) or Fatal( "Can't change ownership of file '$file' to '".ZM_WEB_USER.":".ZM_WEB_GROUP."': $!" ); + } +} + +our $_hasImageInfo = undef; + +sub _checkForImageInfo() +{ + if ( !defined($_hasImageInfo) ) + { + my $result = eval + { + require Image::Info; + Image::Info->import(); + }; + $_hasImageInfo = $@?0:1; + } + return( $_hasImageInfo ); +} + +sub createEvent( $;$ ) +{ + my $event = shift; + + Debug( "Creating event" ); + #print( Dumper( $event )."\n" ); + + _checkForImageInfo(); + + my $dbh = zmDbConnect(); + + if ( $event->{monitor} ) + { + $event->{MonitorId} = $event->{monitor}->{Id}; + } + elsif ( $event->{MonitorId} ) + { + my $sql = "select * from Monitors where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{MonitorId} ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + $event->{monitor} = $sth->fetchrow_hashref() or Fatal( "Unable to create event, can't load monitor with id '".$event->{MonitorId}."'" ); + $sth->finish(); + } + else + { + Fatal( "Unable to create event, no monitor or monitor id supplied" ); + } + $event->{Name} = "New Event" unless( $event->{Name} ); + $event->{Frames} = int(@{$event->{frames}}); + $event->{TotScore} = $event->{MaxScore} = 0; + + my $lastTimestamp = 0.0; + foreach my $frame ( @{$event->{frames}} ) + { + if ( !$event->{Width} ) + { + if ( $_hasImageInfo ) + { + my $imageInfo = Image::Info::image_info( $frame->{imagePath} ); + if ( $imageInfo->{error} ) + { + Error( "Unable to extract image info from '".$frame->{imagePath}."': ".$imageInfo->{error} ); + } + else + { + ( $event->{Width}, $event->{Height} ) = Image::Info::dim( $imageInfo ); + } + } + } + $frame->{Type} = $frame->{Score}>0?'Alarm':'Normal' unless( $frame->{Type} ); + $frame->{Delta} = $lastTimestamp?($frame->{TimeStamp}-$lastTimestamp):0.0; + $event->{StartTime} = $frame->{TimeStamp} unless ( $event->{StartTime} ); + $event->{TotScore} += $frame->{Score}; + $event->{MaxScore} = $frame->{Score} if ( $frame->{Score} > $event->{MaxScore} ); + $event->{AlarmFrames}++ if ( $frame->{Type} eq 'Alarm' ); + $event->{EndTime} = $frame->{TimeStamp}; + $lastTimestamp = $frame->{TimeStamp}; + } + $event->{Width} = $event->{monitor}->{Width} unless( $event->{Width} ); + $event->{Height} = $event->{monitor}->{Height} unless( $event->{Height} ); + $event->{AvgScore} = $event->{TotScore}/int($event->{AlarmFrames}); + $event->{Length} = $event->{EndTime} - $event->{StartTime}; + + my %formats = ( + StartTime => 'from_unixtime(?)', + EndTime => 'from_unixtime(?)', + ); + + my ( @fields, @formats, @values ); + while ( my ( $field, $value ) = each( %$event ) ) + { + next unless $field =~ /^[A-Z]/; + push( @fields, $field ); + push( @formats, ($formats{$field} or '?') ); + push( @values, $event->{$field} ); + } + + my $sql = "insert into Events (".join(',',@fields).") values (".join(',',@formats).")"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + $event->{Id} = $dbh->{mysql_insertid}; + Info( "Created event ".$event->{Id} ); + + if ( $event->{EndTime} ) + { + $event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id} if ( $event->{Name} eq 'New Event' ); + my $sql = "update Events set Name = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Name}, $event->{Id} ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + } + + my $eventPath = createEventPath( $event ); + + my %frameFormats = ( + TimeStamp => 'from_unixtime(?)', + ); + my $frameId = 1; + foreach my $frame ( @{$event->{frames}} ) + { + $frame->{EventId} = $event->{Id}; + $frame->{FrameId} = $frameId++; + + my ( @fields, @formats, @values ); + while ( my ( $field, $value ) = each( %$frame ) ) + { + next unless $field =~ /^[A-Z]/; + push( @fields, $field ); + push( @formats, ($frameFormats{$field} or '?') ); + push( @values, $frame->{$field} ); + } + + my $sql = "insert into Frames (".join(',',@fields).") values (".join(',',@formats).")"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); + #$frame->{FrameId} = $dbh->{mysql_insertid}; + if ( $frame->{imagePath} ) + { + $frame->{capturePath} = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", $eventPath, $frame->{FrameId} ); + rename( $frame->{imagePath}, $frame->{capturePath} ) or Fatal( "Can't copy ".$frame->{imagePath}." to ".$frame->{capturePath}.": $!" ); + setFileOwner( $frame->{capturePath} ); + if ( 0 && ZM_CREATE_ANALYSIS_IMAGES ) + { + $frame->{analysePath} = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-analyse.jpg", $eventPath, $frame->{FrameId} ); + link( $frame->{capturePath}, $frame->{analysePath} ) or Fatal( "Can't link ".$frame->{capturePath}." to ".$frame->{analysePath}.": $!" ); + setFileOwner( $frame->{analysePath} ); + } + } + } +} + +sub addEventImage( $$ ) +{ + my $event = shift; + my $frame = shift; + + # TBD +} + +sub updateEvent( $ ) +{ + my $event = shift; + + if ( !$event->{EventId} ) + { + Error( "Unable to update event, no event id supplied" ); + return( 0 ); + } + + my $dbh = zmDbConnect(); + + $event->{Name} = $event->{monitor}->{EventPrefix}.$event->{Id} if ( $event->{Name} eq 'New Event' ); + + my %formats = ( + StartTime => 'from_unixtime(?)', + EndTime => 'from_unixtime(?)', + ); + + my ( @values, @sets ); + while ( my ( $field, $value ) = each( %$event ) ) + { + next if ( $field eq 'Id' ); + push( @values, $event->{$field} ); + push( @sets, $field." = ".($formats{$field} or '?') ); + } + my $sql = "update Events set ".join(',',@sets)." where Id = ?"; + push( @values, $event->{Id} ); + + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare sql '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( @values ) or Fatal( "Can't execute sql '$sql': ".$sth->errstr() ); +} + +sub deleteEventFiles( $;$ ) +{ + # + # WARNING assumes running from events directory + # + my $event_id = shift; + my $monitor_id = shift; + $monitor_id = '*' if ( !defined($monitor_id) ); + + if ( ZM_USE_DEEP_STORAGE ) + { + my $link_path = $monitor_id."/*/*/*/.".$event_id; + #Debug( "LP1:$link_path" ); + my @links = glob($link_path); + #Debug( "L:".$links[0].": $!" ); + if ( @links ) + { + ( $link_path ) = ( $links[0] =~ /^(.*)$/ ); # De-taint + #Debug( "LP2:$link_path" ); + + ( my $day_path = $link_path ) =~ s/\.\d+//; + #Debug( "DP:$day_path" ); + my $event_path = $day_path.readlink( $link_path ); + ( $event_path ) = ( $event_path =~ /^(.*)$/ ); # De-taint + #Debug( "EP:$event_path" ); + my $command = "/bin/rm -rf ".$event_path; + #Debug( "C:$command" ); + executeShellCommand( $command ); + + unlink( $link_path ) or Error( "Unable to unlink '$link_path': $!" ); + my @path_parts = split( /\//, $event_path ); + for ( my $i = int(@path_parts)-2; $i >= 1; $i-- ) + { + my $delete_path = join( '/', @path_parts[0..$i] ); + #Debug( "DP$i:$delete_path" ); + my @has_files = glob( $delete_path."/*" ); + #Debug( "HF1:".$has_files[0] ) if ( @has_files ); + last if ( @has_files ); + @has_files = glob( $delete_path."/.[0-9]*" ); + #Debug( "HF2:".$has_files[0] ) if ( @has_files ); + last if ( @has_files ); + my $command = "/bin/rm -rf ".$delete_path; + executeShellCommand( $command ); + } + } + } + else + { + my $command = "/bin/rm -rf $monitor_id/$event_id"; + executeShellCommand( $command ); + } +} + +sub makePath( $;$ ) +{ + my $path = shift; + my $root = shift; + $root = (( $path =~ m|^/| )?'':'.' ) unless( $root ); + + Debug( "Creating path '$path' in $root'\n" ); + my @parts = split( '/', $path ); + my $fullPath = $root; + foreach my $dir ( @parts ) + { + $fullPath .= '/'.$dir; + if ( !-d $fullPath ) + { + if ( -e $fullPath ) + { + Fatal( "Can't create '$fullPath', already exists as non directory" ); + } + else + { + Debug( "Creating '$fullPath'\n" ); + mkdir( $fullPath, 0755 ) or Fatal( "Can't mkdir '$fullPath': $!" ); + setFileOwner( $fullPath ); + } + } + } + return( $fullPath ); +} + +our $testedJSON = 0; +our $hasJSONAny = 0; + +sub _testJSON +{ + return if ( $testedJSON ); + my $result = eval + { + require JSON::Any; + JSON::Any->import(); + }; + $testedJSON = 1; + $hasJSONAny = 1 if ( $result ); +} + +sub _getJSONType( $ ) +{ + my $value = shift; + return( 'null' ) unless( defined($value) ); + return( 'integer' ) if ( $value =~ /^\d+$/ ); + return( 'double' ) if ( $value =~ /^\d+$/ ); + return( 'hash' ) if ( ref($value) eq 'HASH' ); + return( 'array' ) if ( ref($value) eq 'ARRAY' ); + return( 'string' ); +} + +sub jsonEncode( $ ); + +sub jsonEncode( $ ) +{ + my $value = shift; + + _testJSON(); + if ( $hasJSONAny ) + { + my $string = eval { JSON::Any->objToJson( $value ) }; + Fatal( "Unable to encode object to JSON: $@" ) unless( $string ); + return( $string ); + } + + my $type = _getJSONType($value); + if ( $type eq 'integer' || $type eq 'double' ) + { + return( $value ); + } + elsif ( $type eq 'boolean' ) + { + return( $value?'true':'false' ); + } + elsif ( $type eq 'string' ) + { + $value =~ s|(["\\/])|\\$1|g; + $value =~ s|\r?\n|\n|g; + return( '"'.$value.'"' ); + } + elsif ( $type eq 'null' ) + { + return( 'null' ); + } + elsif ( $type eq 'array' ) + { + return( '['.join( ',', map { jsonEncode( $_ ) } @$value ).']' ); + } + elsif ( $type eq 'hash' ) + { + my $result = '{'; + while ( my ( $subKey=>$subValue ) = each( %$value ) ) + { + $result .= ',' if ( $result ne '{' ); + $result .= '"'.$subKey.'":'.jsonEncode( $subValue ); + } + return( $result.'}' ); + } + else + { + Fatal( "Unexpected type '$type'" ); + } +} + +sub jsonDecode( $ ) +{ + my $value = shift; + + _testJSON(); + if ( $hasJSONAny ) + { + my $object = eval { JSON::Any->jsonToObj( $value ) }; + Fatal( "Unable to decode JSON string '$value': $@" ) unless( $object ); + return( $object ); + } + + my $comment = 0; + my $unescape = 0; + my $out = ''; + my @chars = split( //, $value ); + for ( my $i = 0; $i < @chars; $i++ ) + { + if ( !$comment ) + { + if ( $chars[$i] eq ':' ) + { + $out .= '=>'; + } + else + { + $out .= $chars[$i]; + } + } + elsif ( !$unescape ) + { + if ( $chars[$i] eq '\\' ) + { + $unescape = 1; + } + else + { + $out .= $chars[$i]; + } + } + else + { + if ( $chars[$i] ne '/' ) + { + $out .= '\\'; + } + $out .= $chars[$i]; + $unescape = 0; + } + if ( $chars[$i] eq '"' ) + { + $comment = !$comment; + } + } + $out =~ s/=>true/=>1/g; + $out =~ s/=>false/=>0/g; + $out =~ s/=>null/=>undef/g; + $out =~ s/`/'/g; + $out =~ s/qx/qq/g; + ( $out ) = $out =~ m/^({.+})$/; # Detaint and check it's a valid object syntax + my $result = eval $out; + Fatal( $@ ) if ( $@ ); + return( $result ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm new file mode 100644 index 000000000..46095be2e --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Logger.pm @@ -0,0 +1,861 @@ +# ========================================================================== +# +# ZoneMinder Logger 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 debug definitions and functions used by the rest +# of the ZoneMinder scripts +# +package ZoneMinder::Logger; + +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 = ( + 'constants' => [ qw( + DEBUG + INFO + WARNING + ERROR + FATAL + PANIC + NOLOG + ) ], + 'functions' => [ qw( + logInit + logReinit + logTerm + logSetSignal + logClearSignal + logDebugging + logLevel + logTermLevel + logDatabaseLevel + logFileLevel + logSyslogLevel + Mark + Dump + Debug + Info + Warning + Error + Fatal + Panic + ) ] +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Logger Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); + +use DBI; +use Carp; +use POSIX; +use IO::Handle; +use Data::Dumper; +use Time::HiRes qw/gettimeofday/; +use Sys::Syslog; + +use constant { + DEBUG => 1, + INFO => 0, + WARNING => -1, + ERROR => -2, + FATAL => -3, + PANIC => -4, + NOLOG => -5 +}; + +our %codes = ( + &DEBUG => "DBG", + &INFO => "INF", + &WARNING => "WAR", + &ERROR => "ERR", + &FATAL => "FAT", + &PANIC => "PNC", + &NOLOG => "OFF" +); + +our %priorities = ( + &DEBUG => "debug", + &INFO => "info", + &WARNING => "warning", + &ERROR => "err", + &FATAL => "err", + &PANIC => "err" +); + +our $logger; + +sub new +{ + my $class = shift; + my $this = {}; + + $this->{initialised} = undef; + + #$this->{id} = "zmundef"; + ( $this->{id} ) = $0 =~ m|^(?:.*/)?([^/]+?)(?:\.[^/.]+)?$|; + $this->{idRoot} = $this->{id}; + $this->{idArgs} = ""; + + $this->{level} = INFO; + $this->{termLevel} = NOLOG; + $this->{databaseLevel} = NOLOG; + $this->{fileLevel} = NOLOG; + $this->{syslogLevel} = NOLOG; + $this->{effectiveLevel} = INFO; + + $this->{autoFlush} = 1; + $this->{hasTerm} = -t STDERR; + + ( $this->{fileName} = $0 ) =~ s|^.*/||; + $this->{logPath} = ZM_PATH_LOGS; + $this->{logFile} = $this->{logPath}."/".$this->{id}.".log"; + + $this->{trace} = 0; + + bless( $this, $class ); + return $this; +} + +sub BEGIN +{ + # Fake the config variables that are used in case they are not defined yet + # Only really necessary to support upgrade from previous version + if ( !eval('defined(ZM_LOG_DEBUG)') ) + { + no strict 'subs'; + no strict 'refs'; + my %dbgConfig = ( + ZM_LOG_LEVEL_DATABASE => 0, + ZM_LOG_LEVEL_FILE => 0, + ZM_LOG_LEVEL_SYSLOG => 0, + ZM_LOG_DEBUG => 0, + ZM_LOG_DEBUG_TARGET => "", + ZM_LOG_DEBUG_LEVEL => 1, + ZM_LOG_DEBUG_FILE => "" + ); + while ( my ( $name, $value ) = each( %dbgConfig ) ) + { + *{$name} = sub { $value }; + } + use strict 'subs'; + use strict 'refs'; + } +} + +sub DESTROY +{ + my $this = shift; + $this->terminate(); +} + +sub initialise( @ ) +{ + my $this = shift; + my %options = @_; + + $this->{id} = $options{id} if ( defined($options{id}) ); + + $this->{logPath} = $options{logPath} if ( defined($options{logPath}) ); + + my $tempLogFile; + $tempLogFile = $this->{logPath}."/".$this->{id}.".log"; + $tempLogFile = $options{logFile} if ( defined($options{logFile}) ); + if ( my $logFile = $this->getTargettedEnv('LOG_FILE') ) + { + $tempLogFile = $logFile; + } + + my $tempLevel = INFO; + my $tempTermLevel = $this->{termLevel}; + my $tempDatabaseLevel = $this->{databaseLevel}; + my $tempFileLevel = $this->{fileLevel}; + my $tempSyslogLevel = $this->{syslogLevel}; + + $tempTermLevel = $options{termLevel} if ( defined($options{termLevel}) ); + if ( defined($options{databaseLevel}) ) + { + $tempDatabaseLevel = $options{databaseLevel}; + } + else + { + $tempDatabaseLevel = ZM_LOG_LEVEL_DATABASE; + } + if ( defined($options{fileLevel}) ) + { + $tempFileLevel = $options{fileLevel}; + } + else + { + $tempFileLevel = ZM_LOG_LEVEL_FILE; + } + if ( defined($options{syslogLevel}) ) + { + $tempSyslogLevel = $options{syslogLevel}; + } + else + { + $tempSyslogLevel = ZM_LOG_LEVEL_SYSLOG; + } + + if ( defined($ENV{'LOG_PRINT'}) ) + { + $tempTermLevel = $ENV{'LOG_PRINT'}? DEBUG : NOLOG; + } + + my $level; + $tempLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL')) ); + + $tempTermLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_TERM')) ); + $tempDatabaseLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_DATABASE')) ); + $tempFileLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_FILE')) ); + $tempSyslogLevel = $level if ( defined($level = $this->getTargettedEnv('LOG_LEVEL_SYSLOG')) ); + + if ( ZM_LOG_DEBUG ) + { + foreach my $target ( split( /\|/, ZM_LOG_DEBUG_TARGET ) ) + { + if ( $target eq $this->{id} || $target eq "_".$this->{id} || $target eq $this->{idRoot} || $target eq "_".$this->{idRoot} || $target eq "" ) + { + if ( ZM_LOG_DEBUG_LEVEL > NOLOG ) + { + $tempLevel = $this->limit( ZM_LOG_DEBUG_LEVEL ); + if ( ZM_LOG_DEBUG_FILE ne "" ) + { + $tempLogFile = ZM_LOG_DEBUG_FILE; + $tempFileLevel = $tempLevel; + } + } + } + } + } + + $this->logFile( $tempLogFile ); + + $this->termLevel( $tempTermLevel ); + $this->databaseLevel( $tempDatabaseLevel ); + $this->fileLevel( $tempFileLevel ); + $this->syslogLevel( $tempSyslogLevel ); + + $this->level( $tempLevel ); + + $this->{trace} = $options{trace} if ( defined($options{trace}) ); + + $this->{autoFlush} = $ENV{'LOG_FLUSH'}?1:0 if ( defined($ENV{'LOG_FLUSH'}) ); + + $this->{initialised} = !undef; + + Debug( "LogOpts: level=".$codes{$this->{level}}."/".$codes{$this->{effectiveLevel}}.", screen=".$codes{$this->{termLevel}}.", database=".$codes{$this->{databaseLevel}}.", logfile=".$codes{$this->{fileLevel}}."->".$this->{logFile}.", syslog=".$codes{$this->{syslogLevel}} ); +} + +sub terminate() +{ + my $this = shift; + return unless ( $this->{initialised} ); + $this->syslogLevel( NOLOG ); + $this->fileLevel( NOLOG ); + $this->databaseLevel( NOLOG ); + $this->termLevel( NOLOG ); +} + +sub reinitialise() +{ + my $this = shift; + + return unless ( $this->{initialised} ); + + # Bit of a nasty hack to reopen connections to log files and the DB + my $syslogLevel = $this->syslogLevel(); + $this->syslogLevel( NOLOG ); + my $logfileLevel = $this->fileLevel(); + $this->fileLevel( NOLOG ); + my $databaseLevel = $this->databaseLevel(); + $this->databaseLevel( NOLOG ); + my $screenLevel = $this->termLevel(); + $this->termLevel( NOLOG ); + + $this->syslogLevel( $syslogLevel ) if ( $syslogLevel > NOLOG ); + $this->fileLevel( $logfileLevel ) if ( $logfileLevel > NOLOG ); + $this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG ); + $this->databaseLevel( $databaseLevel ) if ( $databaseLevel > NOLOG ); +} + +sub limit( $ ) +{ + my $this = shift; + my $level = shift; + return( DEBUG ) if ( $level > DEBUG ); + return( NOLOG ) if ( $level < NOLOG ); + return( $level ); +} + +sub getTargettedEnv( $ ) +{ + my $this = shift; + my $name = shift; + my $envName = $name."_".$this->{id}; + my $value; + $value = $ENV{$envName} if ( defined($ENV{$envName}) ); + if ( !defined($value) && $this->{id} ne $this->{idRoot} ) + { + $envName = $name."_".$this->{idRoot}; + $value = $ENV{$envName} if ( defined($ENV{$envName}) ); + } + if ( !defined($value) ) + { + $value = $ENV{$name} if ( defined($ENV{$name}) ); + } + if ( defined($value) ) + { + ( $value ) = $value =~ m/(.*)/; + } + return( $value ); +} + +sub fetch() +{ + if ( !$logger ) + { + $logger = ZoneMinder::Logger->new(); + $logger->initialise( 'syslogLevel'=>INFO, 'databaseLevel'=>INFO ); + } + return( $logger ); +} + +sub id( ;$ ) +{ + my $this = shift; + my $id = shift; + if ( defined($id) && $this->{id} ne $id ) + { + # Remove whitespace + $id =~ s/\S//g; + # Replace non-alphanum with underscore + $id =~ s/[^a-zA-Z_]/_/g; + + if ( $this->{id} ne $id ) + { + $this->{id} = $this->{idRoot} = $id; + if ( $id =~ /^([^_]+)_(.+)$/ ) + { + $this->{idRoot} = $1; + $this->{idArgs} = $2; + } + } + } + return( $this->{id} ); +} + +sub level( ;$ ) +{ + my $this = shift; + my $level = shift; + if ( defined($level) ) + { + $this->{level} = $this->limit( $level ); + $this->{effectiveLevel} = NOLOG; + $this->{effectiveLevel} = $this->{termLevel} if ( $this->{termLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{databaseLevel} if ( $this->{databaseLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{fileLevel} if ( $this->{fileLevel} > $this->{effectiveLevel} ); + $this->{effectiveLevel} = $this->{syslogLevel} if ( $this->{syslogLevel} > $this->{level} ); + $this->{effectiveLevel} = $this->{level} if ( $this->{effectiveLevel} > $this->{level} ); + } + return( $this->{level} ); +} + +sub debugOn() +{ + my $this = shift; + return( $this->{effectiveLevel} >= DEBUG ); +} + +sub trace( ;$ ) +{ + my $this = shift; + $this->{trace} = $_[0] if ( @_ ); + return( $this->{trace} ); +} + +sub termLevel( ;$ ) +{ + my $this = shift; + my $termLevel = shift; + if ( defined($termLevel) ) + { + $termLevel = NOLOG if ( !$this->{hasTerm} ); + $termLevel = $this->limit( $termLevel ); + if ( $this->{termLevel} != $termLevel ) + { + $this->{termLevel} = $termLevel; + } + } + return( $this->{termLevel} ); +} + +sub databaseLevel( ;$ ) +{ + my $this = shift; + my $databaseLevel = shift; + if ( defined($databaseLevel) ) + { + $databaseLevel = $this->limit( $databaseLevel ); + if ( $this->{databaseLevel} != $databaseLevel ) + { + if ( $databaseLevel > NOLOG && $this->{databaseLevel} <= NOLOG ) + { + if ( !$this->{dbh} ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + + if ( defined($port) ) + { + $this->{dbh} = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".$host.";port=".$port, ZM_DB_USER, ZM_DB_PASS ); + } + else + { + $this->{dbh} = DBI->connect( "DBI:mysql:database=".ZM_DB_NAME.";host=".ZM_DB_HOST, ZM_DB_USER, ZM_DB_PASS ); + } + if ( !$this->{dbh} ) + { + $databaseLevel = NOLOG; + Error( "Unable to write log entries to DB, can't connect to database '".ZM_DB_NAME."' on host '".ZM_DB_HOST."'" ); + } + else + { + $this->{dbh}->{AutoCommit} = 1; + Fatal( "Can't set AutoCommit on in database connection" ) unless( $this->{dbh}->{AutoCommit} ); + $this->{dbh}->{mysql_auto_reconnect} = 1; + Fatal( "Can't set mysql_auto_reconnect on in database connection" ) unless( $this->{dbh}->{mysql_auto_reconnect} ); + $this->{dbh}->trace( 0 ); + } + } + } + elsif ( $databaseLevel <= NOLOG && $this->{databaseLevel} > NOLOG ) + { + if ( $this->{dbh} ) + { + $this->{dbh}->disconnect(); + undef($this->{dbh}); + } + } + $this->{databaseLevel} = $databaseLevel; + } + } + return( $this->{databaseLevel} ); +} + +sub fileLevel( ;$ ) +{ + my $this = shift; + my $fileLevel = shift; + if ( defined($fileLevel) ) + { + $fileLevel = $this->limit($fileLevel); + if ( $this->{fileLevel} != $fileLevel ) + { + $this->closeFile() if ( $this->{fileLevel} > NOLOG ); + $this->{fileLevel} = $fileLevel; + $this->openFile() if ( $this->{fileLevel} > NOLOG ); + } + } + return( $this->{fileLevel} ); +} + +sub syslogLevel( ;$ ) +{ + my $this = shift; + my $syslogLevel = shift; + if ( defined($syslogLevel) ) + { + $syslogLevel = $this->limit($syslogLevel); + if ( $this->{syslogLevel} != $syslogLevel ) + { + $this->closeSyslog() if ( $syslogLevel <= NOLOG && $this->{syslogLevel} > NOLOG ); + $this->openSyslog() if ( $syslogLevel > NOLOG && $this->{syslogLevel} <= NOLOG ); + $this->{syslogLevel} = $syslogLevel; + } + } + return( $this->{syslogLevel} ); +} + +sub openSyslog() +{ + my $this = shift; + openlog( $this->{id}, "pid", "local1" ); +} + +sub closeSyslog() +{ + my $this = shift; + #closelog(); +} + +sub logFile( $ ) +{ + my $this = shift; + my $logFile = shift; + if ( $logFile =~ /^(.+)\+$/ ) + { + $this->{logFile} = $1.'.'.$$; + } + else + { + $this->{logFile} = $logFile; + } +} + +sub openFile() +{ + my $this = shift; + if ( open( LOGFILE, ">>".$this->{logFile} ) ) + { + LOGFILE->autoflush() if ( $this->{autoFlush} ); + + my $webUid = (getpwnam( ZM_WEB_USER ))[2]; + my $webGid = (getgrnam( ZM_WEB_GROUP ))[2]; + if ( $> == 0 ) + { + chown( $webUid, $webGid, $this->{logFile} ) or Fatal( "Can't change permissions on log file '".$this->{logFile}."': $!" ) + } + } + else + { + $this->fileLevel( NOLOG ); + Error( "Can't open log file '".$this->{logFile}."': $!" ); + } +} + +sub closeFile() +{ + my $this = shift; + close( LOGFILE ) if ( fileno(LOGFILE) ); +} + +sub logPrint( $;$ ) +{ + my $this = shift; + my $level = shift; + my $string = shift; + + if ( $level <= $this->{effectiveLevel} ) + { + $string =~ s/[\r\n]+$//g; + + my $code = $codes{$level}; + + my ($seconds, $microseconds) = gettimeofday(); + my $message = sprintf( "%s.%06d %s[%d].%s [%s]", strftime( "%x %H:%M:%S", localtime( $seconds ) ), $microseconds, $this->{id}, $$, $code, $string ); + if ( $this->{trace} ) + { + $message = Carp::shortmess( $message ); + } + else + { + $message = $message."\n"; + } + syslog( $priorities{$level}, $code." [%s]", $string ) if ( $level <= $this->{syslogLevel} ); + print( LOGFILE $message ) if ( $level <= $this->{fileLevel} ); + if ( $level <= $this->{databaseLevel} ) + { + my $sql = "insert into Logs ( TimeKey, Component, Pid, Level, Code, Message, File, Line ) values ( ?, ?, ?, ?, ?, ?, ?, NULL )"; + $this->{sth} = $this->{dbh}->prepare_cached( $sql ); + if ( !$this->{sth} ) + { + $this->{databaseLevel} = NOLOG; + Fatal( "Can't prepare log entry '$sql': ".$this->{dbh}->errstr() ); + } + my $res = $this->{sth}->execute( $seconds+($microseconds/1000000.0), $this->{id}, $$, $level, $code, $string, $this->{fileName} ); + if ( !$res ) + { + $this->{databaseLevel} = NOLOG; + Fatal( "Can't execute log entry '$sql': ".$this->{sth}->errstr() ); + } + } + print( STDERR $message ) if ( $level <= $this->{termLevel} ); + } +} + +sub logInit( ;@ ) +{ + my %options = @_ ? @_ : (); + $logger = ZoneMinder::Logger->new() if ( !$logger ); + $logger->initialise( %options ); +} + +sub logReinit() +{ + fetch()->reinitialise(); +} + +sub logTerm +{ + return unless ( $logger ); + $logger->terminate(); + $logger = undef; +} + +sub logHupHandler() +{ + my $savedErrno = $!; + return unless( $logger ); + fetch()->reinitialise(); + logSetSignal(); + $! = $savedErrno; +} + +sub logSetSignal() +{ + $SIG{HUP} = \&logHupHandler; +} + +sub logClearSignal() +{ + $SIG{HUP} = 'DEFAULT'; +} + +sub logLevel( ;$ ) +{ + return( fetch()->level( @_ ) ); +} + +sub logDebugging() +{ + return( fetch()->debugOn() ); +} + +sub logTermLevel( ;$ ) +{ + return( fetch()->termLevel( @_ ) ); +} + +sub logDatabaseLevel( ;$ ) +{ + return( fetch()->databaseLevel( @_ ) ); +} + +sub logFileLevel( ;$ ) +{ + return( fetch()->fileLevel( @_ ) ); +} + +sub logSyslogLevel( ;$ ) +{ + return( fetch()->syslogLevel( @_ ) ); +} + +sub Mark( ;$$ ) +{ + my $level = shift; + $level = DEBUG unless( defined($level) ); + my $tag = "Mark"; + fetch()->logPrint( $level, $tag ); +} + +sub Dump( \$;$ ) +{ + my $var = shift; + my $label = shift; + $label = "VAR" unless( defined($label) ); + fetch()->logPrint( DEBUG, Data::Dumper->Dump( [ $var ], [ $label ] ) ); +} + +sub Debug( @ ) +{ + fetch()->logPrint( DEBUG, @_ ); +} + +sub Info( @ ) +{ + fetch()->logPrint( INFO, @_ ); +} + +sub Warning( @ ) +{ + fetch()->logPrint( WARNING, @_ ); +} + +sub Error( @ ) +{ + fetch()->logPrint( ERROR, @_ ); +} + +sub Fatal( @ ) +{ + fetch()->logPrint( FATAL, @_ ); + exit( -1 ); +} + +sub Panic( @ ) +{ + fetch()->logPrint( PANIC, @_ ); + confess( $_[0] ); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::Logger - ZoneMinder Logger module + +=head1 SYNOPSIS + + use ZoneMinder::Logger; + use ZoneMinder::Logger qw(:all); + + logInit( "myproc", DEBUG ); + + Debug( "This is what is happening" ); + Info( "Something interesting is happening" ); + Warning( "Something might be going wrong." ); + Error( "Something has gone wrong!!" ); + Fatal( "Something has gone badly wrong, gotta stop!!" ); + Panic( "Something fundamental has gone wrong, die with stack trace ); + +=head1 DESCRIPTION + +The ZoneMinder:Logger module contains the common debug and error reporting routines used by the ZoneMinder scripts. + +To use debug in your scripts you need to include this module, and call logInit. Thereafter you can sprinkle Debug or Error calls etc throughout the code safe in the knowledge that they will be reported to your error log, and possibly the syslogger, in a meaningful and consistent format. + +Debug is discussed in terms of levels where 1 and above (currently only 1 for scripts) is considered debug, 0 is considered as informational, -1 is a warning, -2 is an error and -3 is a fatal error or panic. Where levels are mentioned below as thresholds the value given and anything with a lower level (ie. more serious) will be included. + +=head1 METHODS + +=over 4 + +=item logInit ( $id, %options ); + +Initialises the debug and prepares the logging for forthcoming operations. If not called explicitly it will be called by the first debug call in your script, but with default (and probably meaningless) options. The only compulsory arguments are $id which must be a string that will identify debug coming from this script in mixed logs. Other options may be provided as below, + + Option Default Description + --------- --------- ----------- + level INFO The initial debug level which defines which statements are output and which are ignored + trace 0 Whether to use the Carp::shortmess format in debug statements to identify where the debug was emitted from + termLevel NOLOG At what level debug is written to terminal standard error, 0 is no, 1 is yes, 2 is write only if terminal + databaseLevel INFO At what level debug is written to the Log table in the database; + fileLevel NOLOG At what level debug is written to a log file of the format of .log in the standard log directory. + syslogLevel INFO At what level debug is written to syslog. + +To disable any of these action entirely set to NOLOG + +=item logTerm (); + +Used to end the debug session and close any logs etc. Not usually necessary. + +=item $id = logId ( [$id] ); + +=item $level = logLevel ( [$level] ); + +=item $trace = logTrace ( [$trace] ); + +=item $level = logLevel ( [$level] ); + +=item $termLevel = logTermLevel ( [$termLevel] ); + +=item $databaseLevel = logDatabaseLevel ( [$databaseLevel] ); + +=item $fileLevel = logFileLevel ( [$fileLevel] ); + +=item $syslogLevel = logSyslogLevel ( [$syslogLevel] ); + +These methods can be used to get and set the current settings as defined in logInit. + +=item Debug( $string ); + +This method will output a debug message if the current debug level permits it, otherwise does nothing. This message will be tagged with the DBG string in the logs. + +=item Info( $string ); + +This method will output an informational message if the current debug level permits it, otherwise does nothing. This message will be tagged with the INF string in the logs. + +=item Warning( $string ); + +This method will output a warning message if the current debug level permits it, otherwise does nothing. This message will be tagged with the WAR string in the logs. + +=item Error( $string ); + +This method will output an error message if the current debug level permits it, otherwise does nothing. This message will be tagged with the ERR string in the logs. + +=item Fatal( $string ); + +This method will output a fatal error message and then die if the current debug level permits it, otherwise does nothing. This message will be tagged with the FAT string in the logs. + +=item Panic( $string ); + +This method will output a panic error message and then die with a stack trace if the current debug level permits it, otherwise does nothing. This message will be tagged with the PNC string in the logs. + +=head2 EXPORT + +None by default. +The :constants tag will export the debug constants which define the various levels of debug +The :variables tag will export variables containing the current debug id and level +The :functions tag will export the debug functions. This or :all is what you would normally use. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +Carp +Sys::Syslog + +The ZoneMinder README file Troubleshooting section for an extended discussion on the use and configuration of syslog with ZoneMinder. + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm new file mode 100644 index 000000000..86037713d --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm @@ -0,0 +1,873 @@ +# ========================================================================== +# +# ZoneMinder Memory Access Module, $Date: 2008-02-25 10:13:13 +0000 (Mon, 25 Feb 2008) $, $Revision: 2323 $ +# 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::Memory; + +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 = ( + 'constants' => [ qw( + STATE_IDLE + STATE_PREALARM + STATE_ALARM + STATE_ALERT + STATE_TAPE + ACTION_GET + ACTION_SET + ACTION_RELOAD + ACTION_SUSPEND + ACTION_RESUME + TRIGGER_CANCEL + TRIGGER_ON + TRIGGER_OFF + ) ], + 'functions' => [ qw( + zmMemVerify + zmMemInvalidate + zmMemRead + zmMemWrite + zmMemTidy + zmGetMonitorState + zmGetAlarmLocation + zmIsAlarmed + zmInAlarm + zmHasAlarmed + zmGetLastEvent + zmGetLastWriteTime + zmGetLastReadTime + zmMonitorEnable + zmMonitorDisable + zmMonitorSuspend + zmMonitorResume + zmTriggerEventOn + zmTriggerEventOff + zmTriggerEventCancel + zmTriggerShowtext + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Shared Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +use constant STATE_IDLE => 0; +use constant STATE_PREALARM => 1; +use constant STATE_ALARM => 2; +use constant STATE_ALERT => 3; +use constant STATE_TAPE => 4; + +use constant ACTION_GET => 1; +use constant ACTION_SET => 2; +use constant ACTION_RELOAD => 4; +use constant ACTION_SUSPEND => 16; +use constant ACTION_RESUME => 32; + +use constant TRIGGER_CANCEL => 0; +use constant TRIGGER_ON => 1; +use constant TRIGGER_OFF => 2; + +use Storable qw( freeze thaw ); + +if ( "yes" eq 'yes' ) # 'yes' if memory is mmapped +{ + require ZoneMinder::Memory::Mapped; + ZoneMinder::Memory::Mapped->import(); +} +else +{ + require ZoneMinder::Memory::Shared; + ZoneMinder::Memory::Shared->import(); +} + +# Native architecture +our $arch = int(3.2*length(~0)); +our $native = $arch/8; +our $mem_seq = 0; + +our $mem_data = +{ + "shared_data" => { "type"=>"SharedData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_read_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_event" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "action" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "brightness" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "hue" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "colour" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "contrast" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "valid" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "active" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "signal" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "format" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "imagesize" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "control_state" => { "type"=>"uint8[256]", "seq"=>$mem_seq++ }, + } + }, + "trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "padding" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_cause" => { "type"=>"int8[32]", "seq"=>$mem_seq++ }, + "trigger_text" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + "trigger_showtext" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + } + }, + "end" => { "seq"=>$mem_seq++, "size"=> 0 } +}; + +our $mem_size = 0; +our $mem_verified = {}; + +sub zmMemInit +{ + my $offset = 0; + + foreach my $section_data ( sort { $a->{seq} <=> $b->{seq} } values( %$mem_data ) ) + { + $section_data->{offset} = $offset; + $section_data->{align} = 0; + + if ( $section_data->{align} > 1 ) + { + my $rem = $offset % $section_data->{align}; + if ( $rem > 0 ) + { + $offset += ($section_data->{align} - $rem); + } + } + foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) ) + { + if ( $member_data->{type} eq "long" || $member_data->{type} eq "ulong" || $member_data->{type} eq "size_t") + { + $member_data->{size} = $member_data->{align} = $native; + } + elsif( $member_data->{type} eq "int64" || $member_data->{type} eq "uint64" || $member_data->{type} eq "time_t64") + { + $member_data->{size} = $member_data->{align} = 8; + } + elsif ( $member_data->{type} eq "int32" || $member_data->{type} eq "uint32" || $member_data->{type} eq "bool4" ) + { + $member_data->{size} = $member_data->{align} = 4; + } + elsif ($member_data->{type} eq "int16" || $member_data->{type} eq "uint16") + { + $member_data->{size} = $member_data->{align} = 2; + } + elsif ( $member_data->{type} eq "int8" || $member_data->{type} eq "uint8" || $member_data->{type} eq "bool1" ) + { + $member_data->{size} = $member_data->{align} = 1; + } + elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) + { + $member_data->{size} = $1; + $member_data->{align} = 1; + } + else + { + Fatal( "Unexpected type '".$member_data->{type}."' found in shared data definition." ); + } + + if ( $member_data->{align} > 1 && ($offset%$member_data->{align}) > 0 ) + { + $offset += ($member_data->{align} - ($offset%$member_data->{align})); + } + $member_data->{offset} = $offset; + $offset += $member_data->{size} + } + $section_data->{size} = $offset - $section_data->{offset}; + } + + $mem_size = $offset; +} + +&zmMemInit(); + +sub zmMemVerify( $ ) +{ + my $monitor = shift; + if ( !zmMemAttach( $monitor, $mem_size ) ) + { + return( undef ); + } + + my $mem_key = zmMemKey( $monitor ); + if ( !defined($mem_verified->{$mem_key}) ) + { + my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); + if ( $sd_size != $mem_data->{shared_data}->{size} ) + { + if ( $sd_size ) + { + Error( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + else + { + Debug( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + return( undef ); + } + my $td_size = zmMemRead( $monitor, "trigger_data:size", 1 ); + if ( $td_size != $mem_data->{trigger_data}->{size} ) + { + if ( $td_size ) + { + Error( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + else + { + Debug( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + return( undef ); + } + $mem_verified->{$mem_key} = !undef; + } + return( !undef ); +} + +sub zmMemRead( $$;$ ) +{ + my $monitor = shift; + my $fields = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + if ( !ref($fields) ) + { + $fields = [ $fields ]; + } + my @values; + foreach my $field ( @$fields ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data = zmMemGet( $monitor, $offset, $size ); + if ( !defined($data) ) + { + Error( "Unable to read '$field' from memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + my $value; + if ( $type eq "long" ) + { + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int32" ) + { + ( $value ) = unpack( "l", $data ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + ( $value ) = unpack( "L", $data ); + } + elsif ( $type eq "int16" ) + { + ( $value ) = unpack( "s", $data ); + } + elsif ( $type eq "uint16" ) + { + ( $value ) = unpack( "S", $data ); + } + elsif ( $type eq "int8" ) + { + ( $value ) = unpack( "c", $data ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + ( $value ) = unpack( "C", $data ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + ( $value ) = unpack( "Z".$size, $data ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + ( $value ) = unpack( "C".$size, $data ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + push( @values, $value ); + } + if ( wantarray() ) + { + return( @values ) + } + return( $values[0] ); +} + +sub zmMemInvalidate( $ ) +{ + my $monitor = shift; + my $mem_key = zmMemKey($monitor); + if ( $mem_key ) + { + delete $mem_verified->{$mem_key}; + zmMemDetach( $monitor ); + } +} + +sub zmMemTidy() +{ + zmMemClean(); +} + +sub zmMemWrite( $$;$ ) +{ + my $monitor = shift; + my $field_values = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + while ( my ( $field, $value ) = each( %$field_values ) ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data; + if ( $type eq "long" ) + { + $data = pack( "l!", $value ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + $data = pack( "L!", $value ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "l!", $value ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "L!", $value ); + } + elsif ( $type eq "int32" ) + { + $data = pack( "l", $value ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + $data = pack( "L", $value ); + } + elsif ( $type eq "int16" ) + { + $data = pack( "s", $value ); + } + elsif ( $type eq "uint16" ) + { + $data = pack( "S", $value ); + } + elsif ( $type eq "int8" ) + { + $data = pack( "c", $value ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + $data = pack( "C", $value ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + $data = pack( "Z".$size, $value ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + $data = pack( "C".$size, $value ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + + if ( !zmMemPut( $monitor, $offset, $size, $data ) ) + { + Error( "Unable to write '$value' to '$field' in memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + } + return( !undef ); +} + +sub zmGetMonitorState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:state" ) ); +} + +sub zmGetAlarmLocation( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, [ "shared_data:alarm_x", "shared_data:alarm_y" ] ) ); +} + +sub zmSetControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmMemWrite( $monitor, { "shared_data:control_state" => $control_state } ); +} + +sub zmGetControlState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:control_state" ) ); +} + +sub zmSaveControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmSetControlState( $monitor, freeze( $control_state ) ); +} + +sub zmRestoreControlState( $ ) +{ + my $monitor = shift; + + return( thaw( zmGetControlState( $monitor ) ) ); +} + +sub zmIsAlarmed( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM ); +} + +sub zmInAlarm( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM || $state == STATE_ALERT ); +} + +sub zmHasAlarmed( $$ ) +{ + my $monitor = shift; + my $last_event_id = shift; + + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] ); + + if ( $state == STATE_ALARM || $state == STATE_ALERT ) + { + return( $last_event ); + } + elsif( $last_event != $last_event_id ) + { + return( $last_event ); + } + return( undef ); +} + +sub zmGetLastEvent( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_event" ) ); +} + +sub zmGetLastWriteTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_write_time" ) ); +} + +sub zmGetLastReadTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_read_time" ) ); +} + +sub zmGetMonitorActions( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:action" ) ); +} + +sub zmMonitorEnable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorDisable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorSuspend( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorResume( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmGetTriggerState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "trigger_data:trigger_state" ) ); +} + +sub zmTriggerEventOn( $$$;$$ ) +{ + my $monitor = shift; + my $score = shift; + my $cause = shift; + my $text = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_score" => $score, + "trigger_data:trigger_cause" => $cause, + }; + $values->{"trigger_data:trigger_text"} = $text if ( defined($text) ); + $values->{"trigger_data:trigger_showtext"} = $showtext if ( defined($showtext) ); + $values->{"trigger_data:trigger_state"} = TRIGGER_ON; # Write state last so event not read incomplete + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventOff( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_OFF, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventCancel( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_CANCEL, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerShowtext( $$ ) +{ + my $monitor = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_showtext" => $showtext, + }; + + zmMemWrite( $monitor, $values ); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::MappedMem - ZoneMinder Mapped Memory access module + +=head1 SYNOPSIS + + use ZoneMinder::MappedMem; + use ZoneMinder::MappedMem qw(:all); + + if ( zmMemVerify( $monitor ) ) + { + $state = zmGetMonitorState( $monitor ); + if ( $state == STATE_ALARM ) + { + ... + } + } + + ( $lri, $lwi ) = zmMemRead( $monitor, [ "shared_data:last_read_index", "shared_data:last_write_index" ] ); + zmMemWrite( $monitor, { "trigger_data:trigger_showtext" => "Some Text" } ); + +=head1 DESCRIPTION + +The ZoneMinder:MappedMem module contains methods for accessing and writing to mapped memory as well as helper methods for common operations. + +The core elements of ZoneMinder used mapped memory to allow multiple access to resources. Although ZoneMinder scripts have used this information before, up until now it was difficult to access and prone to errors. This module introduces a common API for mapped memory access (both reading and writing) making it a lot easier to customise scripts or even create your own. + +All the methods listed below require a 'monitor' parameter. This must be a reference to a hash with at least the 'Id' field set to the monitor id of the mapped memory you wish to access. Using database methods to select the monitor details will also return this kind of data. Some of the mapped memory methods will add and amend new fields to this hash. + +=over 4 + +=head1 METHODS + +=item zmMemVerify ( $monitor ); + +Verify that the mapped memory of the monitor given exists and is valid. It will return an undefined value if it is not valid. You should generally call this method first before using any of the other methods, but most of the remaining methods will also do so if the memory has not already been verified. + +=item zmMemInvalidate ( $monitor ); + +Following an error, reset the mapped memory ids and attempt to reverify on the next operation. This is mostly used when a mapped memory segment has gone away and been recreated with a different id. + +=item zmMemRead ( $monitor, $readspec ); + +This method is used to read data from mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'readspec' must either be a string of the form "
:" or a reference to an array of strings of the same format. In the first case a single value is returned, in the latter case a list of values is return. Errors will cause undefined to be returned. The allowable sections and field names are described below. + +=item zmMemWrite ( $monitor, $writespec ); + +This method is used to write data to mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'writespec' must be a reference to a hash with keys of the form "
:" and values as the data to be written. Errors will cause undefined to be returned, otherwise a non-undefined value will be returned. The allowable sections and field names are described below. + +=item $state = zmGetMonitorState ( $monitor ); + +Return the current state of the given monitor. This is an integer value and can be compared with the STATE constants given below. + +=item $event_id = zmGetLastEvent ( $monitor ); + +Return the event id of the last event that the monitor generated, or 0 if no event has been generated by the current monitor process. + +=item zmIsAlarmed ( $monitor ); + +Return 1 if the monitor given is currently in an alarm state, 0 otherwise. + +=item zmInAlarm ( $monitor ); + +Return 1 if the monitor given is currently in an alarm or alerted state, 0 otherwise. + +=item zmHasAlarmed ( $monitor ); + +Return 1 if the given monitor is in an alarm state, or has been in an alarm state since the last call to this method. + +=item ( $x, $y ) = zmGetAlarmLocation ( $monitor ); + +Return an x,y pair indicating the image co-ordinates of the centre of the last motion event generated by the given monitor. If no event has been generated by the current monitor process, or the alarm was not motion related, returns -1,-1. + +=item zmGetLastWriteTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was captured by the given monitor and written to shared memory, or 0 otherwise. + +=item zmGetLastReadTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was read from shared memory by the analysis daemon of the given monitor, or 0 otherwise or if the monitor is in monitor only mode. + +=item zmMonitorSuspend ( $monitor ); + +Suspend the given monitor from generating events caused by motion. This method can be used to prevent camera actions such as panning or zooming from causing events. If configured to do so, the monitor may automatically resume after a defined period. + +=item zmMonitorResume ( $monitor ); + +Allow the given monitor to resume generating events caused by motion. + +=item zmTriggerEventOn ( $monitor, $score, $cause [, $text, $showtext ] ); + +Trigger the given monitor to generate an event. You must supply an event score and a cause string indicating the reason for the event. You may also supply a text string containing further details about the event and a showtext string which may be included in the timestamp annotation on any images captured during the event, if configured to do so. + +=item zmTriggerEventOff ( $monitor ); + +Trigger the given monitor to not generate any events. This method does not cancel zmTriggerEventOn, but is exclusive to it. This method is intended to allow external triggers to prevent normal events being generated by monitors in the same way as zmMonitorSuspend but applies to all events and not just motion, and is intended for longer timescales than are appropriate for suspension. + +=item zmTriggerEventCancel ( $monitor ); + +Cancel any previous trigger on or off requests. This stops a triggered alarm if it exists from a previous 'on' and allows events to be generated once more following a previous 'off'. + +=item zmTriggerShowtext ( $monitor, $showtest ); + +Indicate that the given text should be displayed in the timestamp annotation on any images captured, if the format of the annotation string defined for the monitor permits. + +=head1 DATA + +The data fields in mapped memory that may be accessed are as follows. There are two main sections, shared_data which is general data and trigger_data which is used for event triggering. Whilst reading from these fields is harmless, extreme care must be taken when writing to mapped memory, especially in the shared_data section as this is normally written to only by monitor capture and analysis processes. + + shared_data The general mapped memory section + size The size, in bytes, of this section + valid Flag indicating whether this section has been initialised + active Flag indicating whether this monitor is active (enabled/disabled) + signal Flag indicating whether this monitor is reciving a valid signal + state The current monitor state, see the STATE constants below + last_write_index The last index, in the image buffer, that an image has been saved to + last_read_index The last index, in the image buffer, that an image has been analysed from + last_write_time The time (in utc seconds) when the last image was captured + last_read_time The time (in utc seconds) when the last image was analysed + last_event The id of the last event generated by the monitor analysis process, 0 if none + action The monitor actions bitmask, see the ACTION constants below + brightness Read/write location for the current monitor brightness + hue Read/write location for the current monitor hue + colour Read/write location for the current monitor colour + contrast Read/write location for the current monitor contrast + alarm_x Image x co-ordinate (from left) of the centre of the last motion event, -1 if none + alarm_y Image y co-ordinate (from top) of the centre of the last motion event, -1 if none + + trigger_data The triggered event mapped memory section + size The size, in bytes of this section + trigger_state The current trigger state, see the TRIGGER constants below + trigger_score The current triggered event score + trigger_cause The current triggered event cause string + trigger_text The current triggered event descriptive text string + trigger_showtext The triggered text that will be displayed on captured image timestamps + +=head1 CONSTANTS + +The following constants are used by the methods above, but can also be used by user scripts if required. + +=item STATE_IDLE STATE_PREALARM STATE_ALARM STATE_ALERT STATE_TAPE + +These constants define the state of the monitor with respect to alarms and events. They are used in the shared_data:state field. + +=item ACTION_GET ACTION_SET ACTION_RELOAD ACTION_SUSPEND ACTION_RESUME + +These constants defines the various values that can exist in the shared_data:action field. This is a bitmask which when non-zero defines an action that an executing monitor process should take. ACTION_GET requires that the current values of brightness, contrast, colour and hue are taken from the camera and written to the equivalent mapped memory fields. ACTION_SET implies the reverse, that the values in mapped memory should be written to the camera. ACTION_RELOAD signal that the monitor process should reload itself from the database in case any settings have changed there. ACTION_SUSPEND signals that a monitor should stop exaiming images for motion, though other alarms may still occur. ACTION_RESUME sigansl that a monitor should resume motion detectiom. + +=item TRIGGER_CANCEL TRIGGER_ON TRIGGER_OFF + +These constants are used in the definition of external triggers. TRIGGER_CANCEL is used to indicated that any previous trigger settings should be cancelled, TRIGGER_ON signals that an alarm should be created (or continued)) as a result of the current trigger and TRIGGER_OFF signals that the trigger should prevent any alarms from being generated. See the trigger methods above for further details. + +=head1 EXPORT + +None by default. +The :constants tag will export the mapped memory constants which mostly define enumerations for the variables held in memory +The :functions tag will export the mapped memory access functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in new file mode 100644 index 000000000..dfc9da828 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in @@ -0,0 +1,873 @@ +# ========================================================================== +# +# ZoneMinder Memory Access Module, $Date: 2008-02-25 10:13:13 +0000 (Mon, 25 Feb 2008) $, $Revision: 2323 $ +# 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::Memory; + +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 = ( + 'constants' => [ qw( + STATE_IDLE + STATE_PREALARM + STATE_ALARM + STATE_ALERT + STATE_TAPE + ACTION_GET + ACTION_SET + ACTION_RELOAD + ACTION_SUSPEND + ACTION_RESUME + TRIGGER_CANCEL + TRIGGER_ON + TRIGGER_OFF + ) ], + 'functions' => [ qw( + zmMemVerify + zmMemInvalidate + zmMemRead + zmMemWrite + zmMemTidy + zmGetMonitorState + zmGetAlarmLocation + zmIsAlarmed + zmInAlarm + zmHasAlarmed + zmGetLastEvent + zmGetLastWriteTime + zmGetLastReadTime + zmMonitorEnable + zmMonitorDisable + zmMonitorSuspend + zmMonitorResume + zmTriggerEventOn + zmTriggerEventOff + zmTriggerEventCancel + zmTriggerShowtext + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = qw(); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Shared Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +use constant STATE_IDLE => 0; +use constant STATE_PREALARM => 1; +use constant STATE_ALARM => 2; +use constant STATE_ALERT => 3; +use constant STATE_TAPE => 4; + +use constant ACTION_GET => 1; +use constant ACTION_SET => 2; +use constant ACTION_RELOAD => 4; +use constant ACTION_SUSPEND => 16; +use constant ACTION_RESUME => 32; + +use constant TRIGGER_CANCEL => 0; +use constant TRIGGER_ON => 1; +use constant TRIGGER_OFF => 2; + +use Storable qw( freeze thaw ); + +if ( "@ENABLE_MMAP@" eq 'yes' ) # 'yes' if memory is mmapped +{ + require ZoneMinder::Memory::Mapped; + ZoneMinder::Memory::Mapped->import(); +} +else +{ + require ZoneMinder::Memory::Shared; + ZoneMinder::Memory::Shared->import(); +} + +# Native architecture +our $arch = int(3.2*length(~0)); +our $native = $arch/8; +our $mem_seq = 0; + +our $mem_data = +{ + "shared_data" => { "type"=>"SharedData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_read_index" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_event" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "action" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "brightness" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "hue" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "colour" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "contrast" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_x" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "alarm_y" => { "type"=>"int32", "seq"=>$mem_seq++ }, + "valid" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "active" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "signal" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "format" => { "type"=>"uint8", "seq"=>$mem_seq++ }, + "imagesize" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding1" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "epadding2" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "last_write_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "last_read_time" => { "type"=>"time_t64", "seq"=>$mem_seq++ }, + "control_state" => { "type"=>"uint8[256]", "seq"=>$mem_seq++ }, + } + }, + "trigger_data" => { "type"=>"TriggerData", "seq"=>$mem_seq++, "contents"=> { + "size" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_state" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_score" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "padding" => { "type"=>"uint32", "seq"=>$mem_seq++ }, + "trigger_cause" => { "type"=>"int8[32]", "seq"=>$mem_seq++ }, + "trigger_text" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + "trigger_showtext" => { "type"=>"int8[256]", "seq"=>$mem_seq++ }, + } + }, + "end" => { "seq"=>$mem_seq++, "size"=> 0 } +}; + +our $mem_size = 0; +our $mem_verified = {}; + +sub zmMemInit +{ + my $offset = 0; + + foreach my $section_data ( sort { $a->{seq} <=> $b->{seq} } values( %$mem_data ) ) + { + $section_data->{offset} = $offset; + $section_data->{align} = 0; + + if ( $section_data->{align} > 1 ) + { + my $rem = $offset % $section_data->{align}; + if ( $rem > 0 ) + { + $offset += ($section_data->{align} - $rem); + } + } + foreach my $member_data ( sort { $a->{seq} <=> $b->{seq} } values( %{$section_data->{contents}} ) ) + { + if ( $member_data->{type} eq "long" || $member_data->{type} eq "ulong" || $member_data->{type} eq "size_t") + { + $member_data->{size} = $member_data->{align} = $native; + } + elsif( $member_data->{type} eq "int64" || $member_data->{type} eq "uint64" || $member_data->{type} eq "time_t64") + { + $member_data->{size} = $member_data->{align} = 8; + } + elsif ( $member_data->{type} eq "int32" || $member_data->{type} eq "uint32" || $member_data->{type} eq "bool4" ) + { + $member_data->{size} = $member_data->{align} = 4; + } + elsif ($member_data->{type} eq "int16" || $member_data->{type} eq "uint16") + { + $member_data->{size} = $member_data->{align} = 2; + } + elsif ( $member_data->{type} eq "int8" || $member_data->{type} eq "uint8" || $member_data->{type} eq "bool1" ) + { + $member_data->{size} = $member_data->{align} = 1; + } + elsif ( $member_data->{type} =~ /^u?int8\[(\d+)\]$/ ) + { + $member_data->{size} = $1; + $member_data->{align} = 1; + } + else + { + Fatal( "Unexpected type '".$member_data->{type}."' found in shared data definition." ); + } + + if ( $member_data->{align} > 1 && ($offset%$member_data->{align}) > 0 ) + { + $offset += ($member_data->{align} - ($offset%$member_data->{align})); + } + $member_data->{offset} = $offset; + $offset += $member_data->{size} + } + $section_data->{size} = $offset - $section_data->{offset}; + } + + $mem_size = $offset; +} + +&zmMemInit(); + +sub zmMemVerify( $ ) +{ + my $monitor = shift; + if ( !zmMemAttach( $monitor, $mem_size ) ) + { + return( undef ); + } + + my $mem_key = zmMemKey( $monitor ); + if ( !defined($mem_verified->{$mem_key}) ) + { + my $sd_size = zmMemRead( $monitor, "shared_data:size", 1 ); + if ( $sd_size != $mem_data->{shared_data}->{size} ) + { + if ( $sd_size ) + { + Error( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + else + { + Debug( "Shared data size conflict in shared_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{shared_data}->{size}.", got ".$sd_size ); + } + return( undef ); + } + my $td_size = zmMemRead( $monitor, "trigger_data:size", 1 ); + if ( $td_size != $mem_data->{trigger_data}->{size} ) + { + if ( $td_size ) + { + Error( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + else + { + Debug( "Shared data size conflict in trigger_data for monitor ".$monitor->{Name}.", expected ".$mem_data->{triggger_data}->{size}.", got ".$td_size ); + } + return( undef ); + } + $mem_verified->{$mem_key} = !undef; + } + return( !undef ); +} + +sub zmMemRead( $$;$ ) +{ + my $monitor = shift; + my $fields = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + if ( !ref($fields) ) + { + $fields = [ $fields ]; + } + my @values; + foreach my $field ( @$fields ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data = zmMemGet( $monitor, $offset, $size ); + if ( !defined($data) ) + { + Error( "Unable to read '$field' from memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + my $value; + if ( $type eq "long" ) + { + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "l!", $data ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + ( $value ) = unpack( "L!", $data ); + } + elsif ( $type eq "int32" ) + { + ( $value ) = unpack( "l", $data ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + ( $value ) = unpack( "L", $data ); + } + elsif ( $type eq "int16" ) + { + ( $value ) = unpack( "s", $data ); + } + elsif ( $type eq "uint16" ) + { + ( $value ) = unpack( "S", $data ); + } + elsif ( $type eq "int8" ) + { + ( $value ) = unpack( "c", $data ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + ( $value ) = unpack( "C", $data ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + ( $value ) = unpack( "Z".$size, $data ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + ( $value ) = unpack( "C".$size, $data ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + push( @values, $value ); + } + if ( wantarray() ) + { + return( @values ) + } + return( $values[0] ); +} + +sub zmMemInvalidate( $ ) +{ + my $monitor = shift; + my $mem_key = zmMemKey($monitor); + if ( $mem_key ) + { + delete $mem_verified->{$mem_key}; + zmMemDetach( $monitor ); + } +} + +sub zmMemTidy() +{ + zmMemClean(); +} + +sub zmMemWrite( $$;$ ) +{ + my $monitor = shift; + my $field_values = shift; + my $nocheck = shift; + + if ( !($nocheck || zmMemVerify( $monitor )) ) + { + return( undef ); + } + + while ( my ( $field, $value ) = each( %$field_values ) ) + { + my ( $section, $element ) = split( /[\/:.]/, $field ); + Fatal( "Invalid shared data selector '$field'" ) if ( !$section || !$element ); + + my $offset = $mem_data->{$section}->{contents}->{$element}->{offset}; + my $type = $mem_data->{$section}->{contents}->{$element}->{type}; + my $size = $mem_data->{$section}->{contents}->{$element}->{size}; + + my $data; + if ( $type eq "long" ) + { + $data = pack( "l!", $value ); + } + elsif ( $type eq "ulong" || $type eq "size_t" ) + { + $data = pack( "L!", $value ); + } + elsif ( $type eq "int64" || $type eq "time_t64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "l!", $value ); + } + elsif ( $type eq "uint64" ) + { + # The "q" type is only available on 64bit platforms, so use native. + $data = pack( "L!", $value ); + } + elsif ( $type eq "int32" ) + { + $data = pack( "l", $value ); + } + elsif ( $type eq "uint32" || $type eq "bool4" ) + { + $data = pack( "L", $value ); + } + elsif ( $type eq "int16" ) + { + $data = pack( "s", $value ); + } + elsif ( $type eq "uint16" ) + { + $data = pack( "S", $value ); + } + elsif ( $type eq "int8" ) + { + $data = pack( "c", $value ); + } + elsif ( $type eq "uint8" || $type eq "bool1" ) + { + $data = pack( "C", $value ); + } + elsif ( $type =~ /^int8\[\d+\]$/ ) + { + $data = pack( "Z".$size, $value ); + } + elsif ( $type =~ /^uint8\[\d+\]$/ ) + { + $data = pack( "C".$size, $value ); + } + else + { + Fatal( "Unexpected type '".$type."' found for '".$field."'" ); + } + + if ( !zmMemPut( $monitor, $offset, $size, $data ) ) + { + Error( "Unable to write '$value' to '$field' in memory for monitor ".$monitor->{Id} ); + zmMemInvalidate( $monitor ); + return( undef ); + } + } + return( !undef ); +} + +sub zmGetMonitorState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:state" ) ); +} + +sub zmGetAlarmLocation( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, [ "shared_data:alarm_x", "shared_data:alarm_y" ] ) ); +} + +sub zmSetControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmMemWrite( $monitor, { "shared_data:control_state" => $control_state } ); +} + +sub zmGetControlState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:control_state" ) ); +} + +sub zmSaveControlState( $$ ) +{ + my $monitor = shift; + my $control_state = shift; + + zmSetControlState( $monitor, freeze( $control_state ) ); +} + +sub zmRestoreControlState( $ ) +{ + my $monitor = shift; + + return( thaw( zmGetControlState( $monitor ) ) ); +} + +sub zmIsAlarmed( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM ); +} + +sub zmInAlarm( $ ) +{ + my $monitor = shift; + + my $state = zmGetMonitorState( $monitor ); + + return( $state == STATE_ALARM || $state == STATE_ALERT ); +} + +sub zmHasAlarmed( $$ ) +{ + my $monitor = shift; + my $last_event_id = shift; + + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] ); + + if ( $state == STATE_ALARM || $state == STATE_ALERT ) + { + return( $last_event ); + } + elsif( $last_event != $last_event_id ) + { + return( $last_event ); + } + return( undef ); +} + +sub zmGetLastEvent( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_event" ) ); +} + +sub zmGetLastWriteTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_write_time" ) ); +} + +sub zmGetLastReadTime( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:last_read_time" ) ); +} + +sub zmGetMonitorActions( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "shared_data:action" ) ); +} + +sub zmMonitorEnable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorDisable( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorSuspend( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_SUSPEND; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmMonitorResume( $ ) +{ + my $monitor = shift; + + my $action = zmMemRead( $monitor, "shared_data:action" ); + $action |= ACTION_RESUME; + zmMemWrite( $monitor, { "shared_data:action" => $action } ); +} + +sub zmGetTriggerState( $ ) +{ + my $monitor = shift; + + return( zmMemRead( $monitor, "trigger_data:trigger_state" ) ); +} + +sub zmTriggerEventOn( $$$;$$ ) +{ + my $monitor = shift; + my $score = shift; + my $cause = shift; + my $text = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_score" => $score, + "trigger_data:trigger_cause" => $cause, + }; + $values->{"trigger_data:trigger_text"} = $text if ( defined($text) ); + $values->{"trigger_data:trigger_showtext"} = $showtext if ( defined($showtext) ); + $values->{"trigger_data:trigger_state"} = TRIGGER_ON; # Write state last so event not read incomplete + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventOff( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_OFF, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerEventCancel( $ ) +{ + my $monitor = shift; + + my $values = { + "trigger_data:trigger_state" => TRIGGER_CANCEL, + "trigger_data:trigger_score" => 0, + "trigger_data:trigger_cause" => "", + "trigger_data:trigger_text" => "", + "trigger_data:trigger_showtext" => "", + }; + + zmMemWrite( $monitor, $values ); +} + +sub zmTriggerShowtext( $$ ) +{ + my $monitor = shift; + my $showtext = shift; + + my $values = { + "trigger_data:trigger_showtext" => $showtext, + }; + + zmMemWrite( $monitor, $values ); +} + +1; +__END__ + +=head1 NAME + +ZoneMinder::MappedMem - ZoneMinder Mapped Memory access module + +=head1 SYNOPSIS + + use ZoneMinder::MappedMem; + use ZoneMinder::MappedMem qw(:all); + + if ( zmMemVerify( $monitor ) ) + { + $state = zmGetMonitorState( $monitor ); + if ( $state == STATE_ALARM ) + { + ... + } + } + + ( $lri, $lwi ) = zmMemRead( $monitor, [ "shared_data:last_read_index", "shared_data:last_write_index" ] ); + zmMemWrite( $monitor, { "trigger_data:trigger_showtext" => "Some Text" } ); + +=head1 DESCRIPTION + +The ZoneMinder:MappedMem module contains methods for accessing and writing to mapped memory as well as helper methods for common operations. + +The core elements of ZoneMinder used mapped memory to allow multiple access to resources. Although ZoneMinder scripts have used this information before, up until now it was difficult to access and prone to errors. This module introduces a common API for mapped memory access (both reading and writing) making it a lot easier to customise scripts or even create your own. + +All the methods listed below require a 'monitor' parameter. This must be a reference to a hash with at least the 'Id' field set to the monitor id of the mapped memory you wish to access. Using database methods to select the monitor details will also return this kind of data. Some of the mapped memory methods will add and amend new fields to this hash. + +=over 4 + +=head1 METHODS + +=item zmMemVerify ( $monitor ); + +Verify that the mapped memory of the monitor given exists and is valid. It will return an undefined value if it is not valid. You should generally call this method first before using any of the other methods, but most of the remaining methods will also do so if the memory has not already been verified. + +=item zmMemInvalidate ( $monitor ); + +Following an error, reset the mapped memory ids and attempt to reverify on the next operation. This is mostly used when a mapped memory segment has gone away and been recreated with a different id. + +=item zmMemRead ( $monitor, $readspec ); + +This method is used to read data from mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'readspec' must either be a string of the form "
:" or a reference to an array of strings of the same format. In the first case a single value is returned, in the latter case a list of values is return. Errors will cause undefined to be returned. The allowable sections and field names are described below. + +=item zmMemWrite ( $monitor, $writespec ); + +This method is used to write data to mapped memory attached to the given monitor. The mapped memory will be verified if it has not already been. The 'writespec' must be a reference to a hash with keys of the form "
:" and values as the data to be written. Errors will cause undefined to be returned, otherwise a non-undefined value will be returned. The allowable sections and field names are described below. + +=item $state = zmGetMonitorState ( $monitor ); + +Return the current state of the given monitor. This is an integer value and can be compared with the STATE constants given below. + +=item $event_id = zmGetLastEvent ( $monitor ); + +Return the event id of the last event that the monitor generated, or 0 if no event has been generated by the current monitor process. + +=item zmIsAlarmed ( $monitor ); + +Return 1 if the monitor given is currently in an alarm state, 0 otherwise. + +=item zmInAlarm ( $monitor ); + +Return 1 if the monitor given is currently in an alarm or alerted state, 0 otherwise. + +=item zmHasAlarmed ( $monitor ); + +Return 1 if the given monitor is in an alarm state, or has been in an alarm state since the last call to this method. + +=item ( $x, $y ) = zmGetAlarmLocation ( $monitor ); + +Return an x,y pair indicating the image co-ordinates of the centre of the last motion event generated by the given monitor. If no event has been generated by the current monitor process, or the alarm was not motion related, returns -1,-1. + +=item zmGetLastWriteTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was captured by the given monitor and written to shared memory, or 0 otherwise. + +=item zmGetLastReadTime ( $monitor ); + +Returns the time (in utc seconds) since the last image was read from shared memory by the analysis daemon of the given monitor, or 0 otherwise or if the monitor is in monitor only mode. + +=item zmMonitorSuspend ( $monitor ); + +Suspend the given monitor from generating events caused by motion. This method can be used to prevent camera actions such as panning or zooming from causing events. If configured to do so, the monitor may automatically resume after a defined period. + +=item zmMonitorResume ( $monitor ); + +Allow the given monitor to resume generating events caused by motion. + +=item zmTriggerEventOn ( $monitor, $score, $cause [, $text, $showtext ] ); + +Trigger the given monitor to generate an event. You must supply an event score and a cause string indicating the reason for the event. You may also supply a text string containing further details about the event and a showtext string which may be included in the timestamp annotation on any images captured during the event, if configured to do so. + +=item zmTriggerEventOff ( $monitor ); + +Trigger the given monitor to not generate any events. This method does not cancel zmTriggerEventOn, but is exclusive to it. This method is intended to allow external triggers to prevent normal events being generated by monitors in the same way as zmMonitorSuspend but applies to all events and not just motion, and is intended for longer timescales than are appropriate for suspension. + +=item zmTriggerEventCancel ( $monitor ); + +Cancel any previous trigger on or off requests. This stops a triggered alarm if it exists from a previous 'on' and allows events to be generated once more following a previous 'off'. + +=item zmTriggerShowtext ( $monitor, $showtest ); + +Indicate that the given text should be displayed in the timestamp annotation on any images captured, if the format of the annotation string defined for the monitor permits. + +=head1 DATA + +The data fields in mapped memory that may be accessed are as follows. There are two main sections, shared_data which is general data and trigger_data which is used for event triggering. Whilst reading from these fields is harmless, extreme care must be taken when writing to mapped memory, especially in the shared_data section as this is normally written to only by monitor capture and analysis processes. + + shared_data The general mapped memory section + size The size, in bytes, of this section + valid Flag indicating whether this section has been initialised + active Flag indicating whether this monitor is active (enabled/disabled) + signal Flag indicating whether this monitor is reciving a valid signal + state The current monitor state, see the STATE constants below + last_write_index The last index, in the image buffer, that an image has been saved to + last_read_index The last index, in the image buffer, that an image has been analysed from + last_write_time The time (in utc seconds) when the last image was captured + last_read_time The time (in utc seconds) when the last image was analysed + last_event The id of the last event generated by the monitor analysis process, 0 if none + action The monitor actions bitmask, see the ACTION constants below + brightness Read/write location for the current monitor brightness + hue Read/write location for the current monitor hue + colour Read/write location for the current monitor colour + contrast Read/write location for the current monitor contrast + alarm_x Image x co-ordinate (from left) of the centre of the last motion event, -1 if none + alarm_y Image y co-ordinate (from top) of the centre of the last motion event, -1 if none + + trigger_data The triggered event mapped memory section + size The size, in bytes of this section + trigger_state The current trigger state, see the TRIGGER constants below + trigger_score The current triggered event score + trigger_cause The current triggered event cause string + trigger_text The current triggered event descriptive text string + trigger_showtext The triggered text that will be displayed on captured image timestamps + +=head1 CONSTANTS + +The following constants are used by the methods above, but can also be used by user scripts if required. + +=item STATE_IDLE STATE_PREALARM STATE_ALARM STATE_ALERT STATE_TAPE + +These constants define the state of the monitor with respect to alarms and events. They are used in the shared_data:state field. + +=item ACTION_GET ACTION_SET ACTION_RELOAD ACTION_SUSPEND ACTION_RESUME + +These constants defines the various values that can exist in the shared_data:action field. This is a bitmask which when non-zero defines an action that an executing monitor process should take. ACTION_GET requires that the current values of brightness, contrast, colour and hue are taken from the camera and written to the equivalent mapped memory fields. ACTION_SET implies the reverse, that the values in mapped memory should be written to the camera. ACTION_RELOAD signal that the monitor process should reload itself from the database in case any settings have changed there. ACTION_SUSPEND signals that a monitor should stop exaiming images for motion, though other alarms may still occur. ACTION_RESUME sigansl that a monitor should resume motion detectiom. + +=item TRIGGER_CANCEL TRIGGER_ON TRIGGER_OFF + +These constants are used in the definition of external triggers. TRIGGER_CANCEL is used to indicated that any previous trigger settings should be cancelled, TRIGGER_ON signals that an alarm should be created (or continued)) as a result of the current trigger and TRIGGER_OFF signals that the trigger should prevent any alarms from being generated. See the trigger methods above for further details. + +=head1 EXPORT + +None by default. +The :constants tag will export the mapped memory constants which mostly define enumerations for the variables held in memory +The :functions tag will export the mapped memory access functions. +The :all tag will export all above symbols. + + +=head1 SEE ALSO + +http://www.zoneminder.com + +=head1 AUTHOR + +Philip Coombes, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm new file mode 100644 index 000000000..b8745d835 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Mapped.pm @@ -0,0 +1,169 @@ +# ========================================================================== +# +# ZoneMinder Mapped Memory Access Module, $Date: 2008-02-25 10:13:13 +0000 (Mon, 25 Feb 2008) $, $Revision: 2323 $ +# 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 definitions and functions used when accessing mapped memory +# +package ZoneMinder::Memory::Mapped; + +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( + zmMemKey + zmMemAttach + zmMemDetach + zmMemGet + zmMemPut + zmMemClean + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = @EXPORT_OK; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Mapped Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +use Sys::Mmap; + +sub zmMemKey( $ ) +{ + my $monitor = shift; + return( defined($monitor->{MMapAddr})?$monitor->{MMapAddr}:undef ); +} + +sub zmMemAttach( $$ ) +{ + my $monitor = shift; + my $size = shift; + if ( !defined($monitor->{MMapAddr}) ) + { + my $mmap_file = ZM_PATH_MAP."/zm.mmap.".$monitor->{Id}; + if ( !open( MMAP, "+<".$mmap_file ) ) + { + Error( sprintf( "Can't open memory map file '%s': $!\n", $mmap_file ) ); + return( undef ); + } + my $mmap = undef; + my $mmap_addr = mmap( $mmap, $size, PROT_READ|PROT_WRITE, MAP_SHARED, \*MMAP ); + if ( !$mmap_addr || !$mmap ) + { + Error( sprintf( "Can't mmap to file '%s': $!\n", $mmap_file ) ); + return( undef ); + } + $monitor->{MMapHandle} = \*MMAP; + $monitor->{MMapAddr} = $mmap_addr; + $monitor->{MMap} = \$mmap; + } + return( !undef ); +} + +sub zmMemDetach( $ ) +{ + my $monitor = shift; + + if ( $monitor->{MMap} ) + { + munmap( ${$monitor->{MMap}} ); + delete $monitor->{MMap}; + } + if ( $monitor->{MMapAddr} ) + { + delete $monitor->{MMapAddr}; + } + if ( $monitor->{MMapHandle} ) + { + close( $monitor->{MMapHandle} ); + delete $monitor->{MMapHandle}; + } +} + +sub zmMemGet( $$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + + my $mmap = $monitor->{MMap}; + if ( !$mmap || !$$mmap ) + { + Error( sprintf( "Can't read from mapped memory for monitor '%d', gone away?", $monitor->{Id} ) ); + return( undef ); + } + my $data = substr( $$mmap, $offset, $size ); + return( $data ); +} + +sub zmMemPut( $$$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + my $data = shift; + + my $mmap = $monitor->{MMap}; + if ( !$mmap || !$$mmap ) + { + Error( sprintf( "Can't write mapped memory for monitor '%d', gone away?", $monitor->{Id} ) ); + return( undef ); + } + substr( $$mmap, $offset, $size ) = $data; + return( !undef ); +} + +sub zmMemClean +{ + Debug( "Removing memory map files\n" ); + my $mapPath = ZM_PATH_MAP."/zm.mmap.*"; + foreach my $mapFile( glob( $mapPath ) ) + { + ( $mapFile ) = $mapFile =~ /^(.+)$/; + Debug( "Removing memory map file '$mapFile'\n" ); + unlink( $mapFile ); + } +} + +1; +__END__ diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory/Shared.pm b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Shared.pm new file mode 100644 index 000000000..c04e4f413 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory/Shared.pm @@ -0,0 +1,161 @@ +# ========================================================================== +# +# ZoneMinder Shared Memory Access Module, $Date: 2007-08-29 19:11:09 +0100 (Wed, 29 Aug 2007) $, $Revision: 2175 $ +# 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::Memory::Shared; + +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( + zmMemKey + zmMemAttach + zmMemDetach + zmMemGet + zmMemPut + zmMemClean + ) ], +); +push( @{$EXPORT_TAGS{all}}, @{$EXPORT_TAGS{$_}} ) foreach keys %EXPORT_TAGS; + +our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); + +our @EXPORT = @EXPORT_OK; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Shared Memory Facilities +# +# ========================================================================== + +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); + +sub zmMemKey( $ ) +{ + my $monitor = shift; + return( defined($monitor->{ShmKey})?$monitor->{ShmKey}:undef ); +} + +sub zmMemAttach( $$ ) +{ + my $monitor = shift; + my $size = shift; + if ( !defined($monitor->{ShmId}) ) + { + my $shm_key = (hex(ZM_SHM_KEY)&0xffff0000)|$monitor->{Id}; + my $shm_id = shmget( $shm_key, $size, 0 ); + if ( !defined($shm_id) ) + { + Error( sprintf( "Can't get shared memory id '%x', %d: $!\n", $shm_key, $monitor->{Id} ) ); + return( undef ); + } + $monitor->{ShmKey} = $shm_key; + $monitor->{ShmId} = $shm_id; + } + return( !undef ); +} + +sub zmMemDetach( $ ) +{ + my $monitor = shift; + + delete $monitor->{ShmId}; +} + +sub zmMemGet( $$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + + my $shm_key = $monitor->{ShmKey}; + my $shm_id = $monitor->{ShmId}; + + my $data; + if ( !shmread( $shm_id, $data, $offset, $size ) ) + { + Error( sprintf( "Can't read from shared memory '%x/%d': $!", $shm_key, $shm_id ) ); + return( undef ); + } + return( $data ); +} + +sub zmMemPut( $$$$ ) +{ + my $monitor = shift; + my $offset = shift; + my $size = shift; + my $data = shift; + + my $shm_key = $monitor->{ShmKey}; + my $shm_id = $monitor->{ShmId}; + + if ( !shmwrite( $shm_id, $data, $offset, $size ) ) + { + Error( sprintf( "Can't write to shared memory '%x/%d': $!", $shm_key, $shm_id ) ); + return( undef ); + } + return( !undef ); +} + +sub zmMemClean +{ + Debug( "Removing shared memory\n" ); + # Find ZoneMinder shared memory + my $command = "ipcs -m | grep '^".substr( sprintf( "0x%x", hex(ZM_SHM_KEY) ), 0, -2 )."'"; + Debug( "Checking for shared memory with '$command'\n" ); + open( CMD, "$command |" ) or Fatal( "Can't execute '$command': $!" ); + while( ) + { + chomp; + my ( $key, $id ) = split( /\s+/ ); + if ( $id =~ /^(\d+)/ ) + { + $id = $1; + $command = "ipcrm shm $id"; + Debug( "Removing shared memory with '$command'\n" ); + qx( $command ); + } + } + close( CMD ); +} + +1; +__END__ diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm new file mode 100644 index 000000000..0344e6d94 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel.pm @@ -0,0 +1,166 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel 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 base class definition of the trigger channel +# class tree +# +package ZoneMinder::Trigger::Channel; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Database Access +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my $self = {}; + $self->{readable} = !undef; + $self->{writeable} = !undef; + $self->{selectable} = undef; + $self->{state} = 'closed'; + bless( $self, $class ); + return $self; +} + +sub clone +{ + my $self = shift; + my $clone = { %$self }; + bless $clone, ref $self; +} + +sub open() +{ + my $self = shift; + my $class = ref($self) or croak( "Can't get class for non object $self" ); + croak( "Abstract base class method called for object of class $class" ); +} + +sub close() +{ + my $self = shift; + my $class = ref($self) or croak( "Can't get class for non object $self" ); + croak( "Abstract base class method called for object of class $class" ); +} + +sub getState() +{ + my $self = shift; + return( $self->{state} ); +} + +sub isOpen() +{ + my $self = shift; + return( $self->{state} eq "open" ); +} + +sub isConnected() +{ + my $self = shift; + return( $self->{state} eq "connected" ); +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( !exists($self->{$name}) ) + { + croak( "Can't access $name member of object of class $class" ); + } + return( $self->{$name} ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm new file mode 100644 index 000000000..234dae3d7 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/File.pm @@ -0,0 +1,121 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the simple file based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::File; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Handle; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Handle); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Simple file based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Fcntl; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel::Handle->new; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + #sysopen( *sfh, $conn->{path}, O_NONBLOCK|O_RDONLY ) or croak( "Can't sysopen: $!" ); + #open( *sfh, "<".$conn->{path} ) or croak( "Can't open: $!" ); + open( *sfh, "+<".$self->{path} ) or croak( "Can't open: $!" ); + $self->{state} = 'open'; + $self->{handle} = *sfh; +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm new file mode 100644 index 000000000..356bb5aea --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Handle.pm @@ -0,0 +1,154 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the handle based trigger channel +# class +# +package ZoneMinder::Trigger::Channel::Handle; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel; + +our @ISA = qw(ZoneMinder::Trigger::Channel); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base class for handle based trigger channels +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use POSIX; + +sub new +{ + my $class = shift; + my $port = shift; + my $self = ZoneMinder::Trigger::Channel->new(); + $self->{handle} = undef; + bless( $self, $class ); + return $self; +} + +sub spawns +{ + return( undef ); +} + +sub close() +{ + my $self = shift; + close( $self->{handle} ); + $self->{state} = 'closed'; + $self->{handle} = undef; +} + +sub read() +{ + my $self = shift; + my $buffer; + my $nbytes = sysread( $self->{handle}, $buffer, POSIX::BUFSIZ ); + if ( !$nbytes ) + { + return( undef ); + } + Debug( "Read '$buffer' ($nbytes bytes)\n" ); + return( $buffer ); +} + +sub write() +{ + my $self = shift; + my $buffer = shift; + my $nbytes = syswrite( $self->{handle}, $buffer ); + if ( !defined( $nbytes) || $nbytes < length($buffer) ) + { + Error( "Unable to write buffer '".$buffer.", expected ".length($buffer)." bytes, sent ".$nbytes.": $!\n" ); + return( undef ); + } + Debug( "Wrote '$buffer' ($nbytes bytes)\n" ); + return( !undef ); +} + +sub fileno() +{ + my $self = shift; + return( defined($self->{handle})?fileno($self->{handle}):-1 ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm new file mode 100644 index 000000000..68df0980f --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Inet.pm @@ -0,0 +1,142 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the tcp socket based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::Inet; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Spawning; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Spawning); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Internet (TCP) based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Socket; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel::Spawning->new(); + $self->{selectable} = !undef; + $self->{port} = $params{port}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + my $saddr = sockaddr_in( $self->{port}, INADDR_ANY ); + socket( *sfh, PF_INET, SOCK_STREAM, getprotobyname('tcp') ) or croak( "Can't open socket: $!" ); + setsockopt( *sfh, SOL_SOCKET, SO_REUSEADDR, 1 ); + bind( *sfh, $saddr ) or croak( "Can't bind: $!" ); + listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" ); + $self->{state} = 'open'; + $self->{handle} = *sfh; +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_handle = shift; + my $clone = $self->clone(); + $clone->{handle} = $new_handle; + $clone->{state} = 'connected'; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + local *cfh; + my $paddr = accept( *cfh, $self->{handle} ); + return( $self->_spawn( *cfh ) ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm new file mode 100644 index 000000000..7e4ad4730 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Serial.pm @@ -0,0 +1,160 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the serial port trigger channel +# class +# +package ZoneMinder::Trigger::Channel::Serial; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel; + +our @ISA = qw(ZoneMinder::Trigger::Channel); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Serial access trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); +use Device::SerialPort; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel->new; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + my $device = new Device::SerialPort( $self->{path} ); + $device->baudrate(9600); + $device->databits(8); + $device->parity('none'); + $device->stopbits(1); + $device->handshake('none'); + + $device->read_const_time(50); + $device->read_char_time(10); + + $self->{device} = $device; + $self->{state} = 'open'; + $self->{state} = 'connected'; +} + +sub close() +{ + my $self = shift; + $self->{device}->close(); + $self->{state} = 'closed'; +} + +sub read() +{ + my $self = shift; + my $buffer = $self->{device}->lookfor(); + if ( !$buffer || !length($buffer) ) + { + return( undef ); + } + Debug( "Read '$buffer' (".length($buffer)." bytes)\n" ); + return( $buffer ); +} + +sub write() +{ + my $self = shift; + my $buffer = shift; + my $nbytes = $self->{device}->write( $buffer ); + $self->{device}->write_drain(); + if ( !defined( $nbytes) || $nbytes < length($buffer) ) + { + Error( "Unable to write buffer '".$buffer.", expected ".length($buffer)." bytes, sent ".$nbytes.": $!\n" ); + return( undef ); + } + Debug( "Wrote '$buffer' ($nbytes bytes)\n" ); + return( !undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm new file mode 100644 index 000000000..ff726ac38 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Spawning.pm @@ -0,0 +1,112 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the handle based trigger channel +# classes that spawn new connections when connected. +# +package ZoneMinder::Trigger::Channel::Spawning; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Handle; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Handle); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base class for handle based triggers that spawn new connections +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +sub new +{ + my $class = shift; + my $port = shift; + my $self = ZoneMinder::Trigger::Channel::Handle->new(); + $self->{spawns} = !undef; + bless( $self, $class ); + return $self; +} + +sub spawns +{ + return( !undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm new file mode 100644 index 000000000..a671ccd66 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Channel/Unix.pm @@ -0,0 +1,141 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 class definition of the unix socket based trigger +# channel class +# +package ZoneMinder::Trigger::Channel::Unix; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Channel::Spawning; + +our @ISA = qw(ZoneMinder::Trigger::Channel::Spawning); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Unix socket based trigger channel +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; +use Socket; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = ZoneMinder::Trigger::Channel->new; + $self->{selectable} = !undef; + $self->{path} = $params{path}; + bless( $self, $class ); + return $self; +} + +sub open() +{ + my $self = shift; + local *sfh; + unlink( $self->{path} ); + my $saddr = sockaddr_un( $self->{path} ); + socket( *sfh, PF_UNIX, SOCK_STREAM, 0 ) or croak( "Can't open socket: $!" ); + bind( *sfh, $saddr ) or croak( "Can't bind: $!" ); + listen( *sfh, SOMAXCONN ) or croak( "Can't listen: $!" ); + $self->{handle} = *sfh; +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_handle = shift; + my $clone = $self->clone(); + $clone->{handle} = $new_handle; + $clone->{state} = 'connected'; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + local *cfh; + my $paddr = accept( *cfh, $self->{handle} ); + return( $self->_spawn( *cfh ) ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm new file mode 100644 index 000000000..41b332d46 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection.pm @@ -0,0 +1,239 @@ +# ========================================================================== +# +# ZoneMinder Trigger Connection 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 base class definition of the trigger connection +# class tree +# +package ZoneMinder::Trigger::Connection; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Base connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +use Carp; + +our $AUTOLOAD; + +sub new +{ + my $class = shift; + my %params = @_; + my $self = {}; + $self->{name} = $params{name}; + $self->{channel} = $params{channel}; + $self->{input} = $params{mode} =~ /r/i; + $self->{output} = $params{mode} =~ /w/i; + bless( $self, $class ); + return $self; +} + +sub clone +{ + my $self = shift; + my $clone = { %$self }; + bless $clone, ref $self; + return( $clone ); +} + +sub spawns +{ + my $self = shift; + return( $self->{channel}->spawns() ); +} + +sub _spawn( $ ) +{ + my $self = shift; + my $new_channel = shift; + my $clone = $self->clone(); + $clone->{channel} = $new_channel; + return( $clone ); +} + +sub accept() +{ + my $self = shift; + my $new_channel = $self->{channel}->accept(); + return( $self->_spawn( $new_channel ) ); +} + +sub open() +{ + my $self = shift; + return( $self->{channel}->open() ); +} + +sub close() +{ + my $self = shift; + return( $self->{channel}->close() ); +} + +sub fileno() +{ + my $self = shift; + return( $self->{channel}->fileno() ); +} + +sub isOpen() +{ + my $self = shift; + return( $self->{channel}->isOpen() ); +} + +sub isConnected() +{ + my $self = shift; + return( $self->{channel}->isConnected() ); +} + +sub canRead() +{ + my $self = shift; + return( $self->{input} && $self->isConnected() ); +} + +sub canWrite() +{ + my $self = shift; + return( $self->{output} && $self->isConnected() ); +} + +sub getMessages +{ + my $self = shift; + my $buffer = $self->{channel}->read(); + + return( undef ) if ( !defined($buffer) ); + + my @messages = split( /\r?\n/, $buffer ); + return( \@messages ); +} + +sub putMessages +{ + my $self = shift; + my $messages = shift; + + if ( @$messages ) + { + my $buffer = join( "\n", @$messages ); + $buffer .= "\n"; + if ( !$self->{channel}->write( $buffer ) ) + { + Error( "Unable to write buffer '".$buffer." to connection ".$self->{name}." (".$self->fileno().")\n" ); + } + } + return( undef ); +} + +sub timedActions +{ +} + +sub DESTROY +{ +} + +sub AUTOLOAD +{ + my $self = shift; + my $class = ref($self) || croak( "$self not object" ); + my $name = $AUTOLOAD; + $name =~ s/.*://; + if ( exists($self->{$name}) ) + { + return( $self->{$name} ); + } + elsif ( defined($self->{channel}) ) + { + if ( exists($self->{channel}->{$name}) ) + { + return( $self->{channel}->{$name} ); + } + } + croak( "Can't access $name member of object of class $class" ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm new file mode 100644 index 000000000..3bed2b351 --- /dev/null +++ b/scripts/ZoneMinder/lib/ZoneMinder/Trigger/Connection/Example.pm @@ -0,0 +1,134 @@ +# ========================================================================== +# +# ZoneMinder Trigger Channel Handle 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 an example overriden trigger connection class +# +package ZoneMinder::Trigger::Connection::Example; + +use 5.006; +use strict; +use warnings; + +require ZoneMinder::Base; +require ZoneMinder::Trigger::Connection; + +our @ISA = qw(ZoneMinder::Trigger::Connection); + +our $VERSION = $ZoneMinder::Base::VERSION; + +# ========================================================================== +# +# Example overridden connection class +# +# ========================================================================== + +use ZoneMinder::Logger qw(:all); + +sub new +{ + my $class = shift; + my $path = shift; + my $self = ZoneMinder::Trigger::Connection->new( @_ ); + bless( $self, $class ); + return $self; +} + +sub getMessages +{ + my $self = shift; + my $buffer = $self->{channel}->read(); + + return( undef ) if ( !defined($buffer) ); + + Debug( "Handling buffer '$buffer'\n" ); + my @messages = grep { s/-/|/g; 1; } split( /\r?\n/, $buffer ); + return( \@messages ); +} + +sub putMessages +{ + my $self = shift; + my $messages = shift; + + if ( @$messages ) + { + my $buffer = join( "\n", grep{ s/\|/-/; 1; } @$messages ); + $buffer .= "\n"; + if ( !$self->{channel}->write( $buffer ) ) + { + Error( "Unable to write buffer '".$buffer." to connection ".$self->{name}." (".$self->fileno().")\n" ); + } + } + return( undef ); +} + +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::Database; + 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, Ephilip.coombes@zoneminder.comE + +=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 diff --git a/scripts/ZoneMinder/pm_to_blib b/scripts/ZoneMinder/pm_to_blib new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/ZoneMinder/t/ZoneMinder.t b/scripts/ZoneMinder/t/ZoneMinder.t new file mode 100644 index 000000000..6ff60ee25 --- /dev/null +++ b/scripts/ZoneMinder/t/ZoneMinder.t @@ -0,0 +1,17 @@ +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl ZoneMinder.t' + +######################### + +# change 'tests => 1' to 'tests => last_test_to_print'; + +use Test; +BEGIN { plan tests => 1 }; +use ZoneMinder; +ok(1); # If we made it this far, we're ok. + +######################### + +# Insert your test code below, the Test::More module is use()ed here so read +# its man page ( perldoc Test::More ) for help writing this test script. + diff --git a/scripts/zm b/scripts/zm new file mode 100644 index 000000000..52d4aacf0 --- /dev/null +++ b/scripts/zm @@ -0,0 +1,120 @@ +#!/bin/sh +# description: ZoneMinder is the top Linux video camera security and surveillance solution. ZoneMinder is intended for use in single or multi-camera video security applications.Copyright: Philip Coombes, Corey DeLasaux 2003-2008 +# chkconfig: 2345 99 00 +# processname: zmpkg.pl + +# Source function library. +. /etc/rc.d/init.d/functions + +prog=ZoneMinder +ZM_CONFIG="/etc/zm/zm.conf" +pidfile="/var/run/zm" +LOCKFILE=/var/lock/subsys/zm + +loadconf() +{ + if [ -f $ZM_CONFIG ]; then + . $ZM_CONFIG + else + echo "ERROR: $ZM_CONFIG not found." + return 1 + fi +} + +loadconf +command="$ZM_PATH_BIN/zmpkg.pl" + +start() +{ + zmupdate || return $? + loadconf || return $? + #Make sure the directory for our PID folder exists or create one. + [ ! -d $pidfile ] \ + && mkdir -m 774 $pidfile \ + && chown $ZM_WEB_USER:$ZM_WEB_GROUP $pidfile + #Make sure the folder for the socks file exists or create one + GetPath="select Value from Config where Name='ZM_PATH_SOCKS'" + dbHost=`echo $ZM_DB_HOST | cut -d: -f1` + dbPort=`echo $ZM_DB_HOST | cut -d: -s -f2` + if [ "$dbPort" = "" ] + then + ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$ZM_DB_HOST -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'` + else + ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$dbHost -P$dbPort -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'` + fi + [ ! -d $ZM_PATH_SOCK ] \ + && mkdir -m 774 $ZM_PATH_SOCK \ + && chown $ZM_WEB_USER:$ZM_WEB_GROUP $ZM_PATH_SOCK + echo -n $"Starting $prog: " + $command start + RETVAL=$? + [ $RETVAL = 0 ] && success || failure + echo + [ $RETVAL = 0 ] && touch $LOCKFILE + return $RETVAL +} + +stop() +{ + loadconf + echo -n $"Stopping $prog: " + $command stop + RETVAL=$? + [ $RETVAL = 0 ] && success || failure + echo + [ $RETVAL = 0 ] && rm -f $LOCKFILE +} + +zmstatus() +{ + loadconf + result=`$command status` + if [ "$result" = "running" ]; then + echo "ZoneMinder is running" + $ZM_PATH_BIN/zmu -l + RETVAL=0 + else + echo "ZoneMinder is stopped" + RETVAL=1 + fi +} + +zmupdate() +{ + if [ -x $ZM_PATH_BIN/zm_update ]; then + $ZM_PATH_BIN/zm_update -f + fi +} + + +case "$1" in + 'start') + start + ;; + 'stop') + stop + ;; + 'restart') + stop + start + ;; + 'condrestart') + loadconf + result=`$ZM_PATH_BIN/zmdc.pl check` + if [ "$result" = "running" ]; then + $ZM_PATH_BIN/zmdc.pl shutdown > /dev/null + rm -f $LOCKFILE + start + fi + ;; + 'status') + status httpd + status mysqld + zmstatus + ;; + *) + echo "Usage: $0 { start | stop | restart | condrestart | status }" + RETVAL=1 + ;; +esac +exit $RETVAL diff --git a/scripts/zm.in b/scripts/zm.in new file mode 100755 index 000000000..1b7a7f2a3 --- /dev/null +++ b/scripts/zm.in @@ -0,0 +1,120 @@ +#!/bin/sh +# description: ZoneMinder is the top Linux video camera security and surveillance solution. ZoneMinder is intended for use in single or multi-camera video security applications.Copyright: Philip Coombes, Corey DeLasaux 2003-2008 +# chkconfig: 2345 99 00 +# processname: zmpkg.pl + +# Source function library. +. /etc/rc.d/init.d/functions + +prog=ZoneMinder +ZM_CONFIG="@ZM_CONFIG@" +pidfile="@ZM_RUNDIR@" +LOCKFILE=/var/lock/subsys/zm + +loadconf() +{ + if [ -f $ZM_CONFIG ]; then + . $ZM_CONFIG + else + echo "ERROR: $ZM_CONFIG not found." + return 1 + fi +} + +loadconf +command="$ZM_PATH_BIN/zmpkg.pl" + +start() +{ + zmupdate || return $? + loadconf || return $? + #Make sure the directory for our PID folder exists or create one. + [ ! -d $pidfile ] \ + && mkdir -m 774 $pidfile \ + && chown $ZM_WEB_USER:$ZM_WEB_GROUP $pidfile + #Make sure the folder for the socks file exists or create one + GetPath="select Value from Config where Name='ZM_PATH_SOCKS'" + dbHost=`echo $ZM_DB_HOST | cut -d: -f1` + dbPort=`echo $ZM_DB_HOST | cut -d: -s -f2` + if [ "$dbPort" = "" ] + then + ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$ZM_DB_HOST -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'` + else + ZM_PATH_SOCK=`echo $GetPath | mysql -B -h$dbHost -P$dbPort -u$ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME | grep -v '^Value'` + fi + [ ! -d $ZM_PATH_SOCK ] \ + && mkdir -m 774 $ZM_PATH_SOCK \ + && chown $ZM_WEB_USER:$ZM_WEB_GROUP $ZM_PATH_SOCK + echo -n $"Starting $prog: " + $command start + RETVAL=$? + [ $RETVAL = 0 ] && success || failure + echo + [ $RETVAL = 0 ] && touch $LOCKFILE + return $RETVAL +} + +stop() +{ + loadconf + echo -n $"Stopping $prog: " + $command stop + RETVAL=$? + [ $RETVAL = 0 ] && success || failure + echo + [ $RETVAL = 0 ] && rm -f $LOCKFILE +} + +zmstatus() +{ + loadconf + result=`$command status` + if [ "$result" = "running" ]; then + echo "ZoneMinder is running" + $ZM_PATH_BIN/zmu -l + RETVAL=0 + else + echo "ZoneMinder is stopped" + RETVAL=1 + fi +} + +zmupdate() +{ + if [ -x $ZM_PATH_BIN/zm_update ]; then + $ZM_PATH_BIN/zm_update -f + fi +} + + +case "$1" in + 'start') + start + ;; + 'stop') + stop + ;; + 'restart') + stop + start + ;; + 'condrestart') + loadconf + result=`$ZM_PATH_BIN/zmdc.pl check` + if [ "$result" = "running" ]; then + $ZM_PATH_BIN/zmdc.pl shutdown > /dev/null + rm -f $LOCKFILE + start + fi + ;; + 'status') + status httpd + status mysqld + zmstatus + ;; + *) + echo "Usage: $0 { start | stop | restart | condrestart | status }" + RETVAL=1 + ;; +esac +exit $RETVAL diff --git a/scripts/zmaudit.pl b/scripts/zmaudit.pl new file mode 100644 index 000000000..d153b5b39 --- /dev/null +++ b/scripts/zmaudit.pl @@ -0,0 +1,510 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Audit Script, $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 script checks for consistency between the event filesystem and +# the database. If events are found in one and not the other they are +# deleted (optionally). Additionally any monitor event directories that +# do not correspond to a database monitor are similarly disposed of. +# However monitors in the database that don't have a directory are left +# alone as this is valid if they are newly created and have no events +# yet. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant MIN_AGE => 300; # Minimum age when we will delete anything +use constant MAX_AGED_DIRS => 10; # Number of event dirs to check age on +use constant RECOVER_TAG => "(r)"; # Tag to append to event name when recovered +use constant RECOVER_TEXT => "Recovered."; # Text to append to event notes when recovered + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use DBI; +use POSIX; +use File::Find; +use Time::HiRes qw/gettimeofday/; +use Getopt::Long; + +use constant IMAGE_PATH => ZM_PATH_WEB.'/'.ZM_DIR_IMAGES; +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $report = 0; +my $interactive = 0; +my $continuous = 0; + +sub usage +{ + print( " +Usage: zmaudit.pl [-r,-report|-i,-interactive] +Parameters are :- +-r, --report - Just report don't actually do anything +-i, --interactive - Ask before applying any changes +-c, --continuous - Run continuously +"); + exit( -1 ); +} + +sub aud_print( $ ); +sub confirm( ;$$ ); +sub deleteSwapImage(); + +logInit(); +logSetSignal(); + +if ( !GetOptions( 'report'=>\$report, 'interactive'=>\$interactive, 'continuous'=>\$continuous ) ) +{ + usage(); +} + +if ( ($report + $interactive + $continuous) > 1 ) +{ + print( STDERR "Error, only option may be specified\n" ); + usage(); +} + +my $dbh = zmDbConnect(); + +chdir( EVENT_PATH ); + +my $max_image_age = 6/24; # 6 hours +my $max_swap_age = 24/24; # 24 hours +my $image_path = IMAGE_PATH; +my $swap_image_path = ZM_PATH_SWAP; + +my $loop = 1; +my $cleaned = 0; +MAIN: while( $loop ) +{ + my $db_monitors; + my $monitorSelectSql = "select Id from Monitors order by Id"; + my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); + my $eventSelectSql = "select Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age from Events where MonitorId = ? order by Id"; + my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() ); + + $cleaned = 0; + my $res = $monitorSelectSth->execute() or Fatal( "Can't execute: ".$monitorSelectSth->errstr() ); + while( my $monitor = $monitorSelectSth->fetchrow_hashref() ) + { + Debug( "Found database monitor '$monitor->{Id}'" ); + my $db_events = $db_monitors->{$monitor->{Id}} = {}; + my $res = $eventSelectSth->execute( $monitor->{Id} ) or Fatal( "Can't execute: ".$eventSelectSth->errstr() ); + while ( my $event = $eventSelectSth->fetchrow_hashref() ) + { + $db_events->{$event->{Id}} = $event->{Age}; + } + Debug( "Got ".int(keys(%$db_events))." events\n" ); + $eventSelectSth->finish(); + } + $monitorSelectSth->finish(); + + my $fs_monitors; + foreach my $monitor ( <[0-9]*> ) + { + Debug( "Found filesystem monitor '$monitor'" ); + my $fs_events = $fs_monitors->{$monitor} = {}; + ( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); # De-taint + + if ( ZM_USE_DEEP_STORAGE ) + { + foreach my $day_dir ( <$monitor_dir/*/*/*> ) + { + Debug( "Checking $day_dir" ); + ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint + chdir( $day_dir ); + opendir( DIR, "." ) or Fatal( "Can't open directory '$day_dir': $!" ); + my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); + closedir( DIR ); + my $count = 0; + foreach my $event_link ( @event_links ) + { + Debug( "Checking link $event_link" ); + ( my $event = $event_link ) =~ s/^.*\.//; + my $event_path = readlink( $event_link ); + if ( $count++ > MAX_AGED_DIRS ) + { + $fs_events->{$event} = -1; + } + else + { + if ( !-e $event_path ) + { + aud_print( "Event link $day_dir/$event_link does not point to valid target" ); + if ( confirm() ) + { + ( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint + unlink( $event_link ); + $cleaned = 1; + } + } + else + { + $fs_events->{$event} = (time() - ($^T - ((-M $event_path) * 24*60*60))); + } + } + } + chdir( EVENT_PATH ); + } + } + else + { + chdir( $monitor_dir ); + opendir( DIR, "." ) or Fatal( "Can't open directory '$monitor_dir': $!" ); + my @temp_events = sort { $b <=> $a } grep { -d $_ && $_ =~ /^\d+$/ } readdir( DIR ); + closedir( DIR ); + my $count = 0; + foreach my $event ( @temp_events ) + { + if ( $count++ > MAX_AGED_DIRS ) + { + $fs_events->{$event} = -1; + } + else + { + $fs_events->{$event} = (time() - ($^T - ((-M $event) * 24*60*60))); + } + } + chdir( EVENT_PATH ); + } + Debug( "Got ".int(keys(%$fs_events))." events\n" ); + } + redo MAIN if ( $cleaned ); + + $cleaned = 0; + while ( my ( $fs_monitor, $fs_events ) = each(%$fs_monitors) ) + { + if ( my $db_events = $db_monitors->{$fs_monitor} ) + { + if ( $fs_events ) + { + while ( my ( $fs_event, $age ) = each(%$fs_events ) ) + { + if ( !defined($db_events->{$fs_event}) && ($age < 0 || ($age > MIN_AGE)) ) + { + aud_print( "Filesystem event '$fs_monitor/$fs_event' does not exist in database" ); + if ( confirm() ) + { + deleteEventFiles( $fs_event, $fs_monitor ); + $cleaned = 1; + } + } + } + } + } + else + { + aud_print( "Filesystem monitor '$fs_monitor' does not exist in database" ); + if ( confirm() ) + { + my $command = "rm -rf $fs_monitor"; + executeShellCommand( $command ); + $cleaned = 1; + } + } + } + + my $monitor_links; + foreach my $link ( <*> ) + { + next if ( !-l $link ); + next if ( -e $link ); + + aud_print( "Filesystem monitor link '$link' does not point to valid monitor directory" ); + if ( confirm() ) + { + ( $link ) = ( $link =~ /^(.*)$/ ); # De-taint + my $command = "rm $link"; + executeShellCommand( $command ); + $cleaned = 1; + } + } + redo MAIN if ( $cleaned ); + + $cleaned = 0; + my $deleteMonitorSql = "delete low_priority from Monitors where Id = ?"; + my $deleteMonitorSth = $dbh->prepare_cached( $deleteMonitorSql ) or Fatal( "Can't prepare '$deleteMonitorSql': ".$dbh->errstr() ); + my $deleteEventSql = "delete low_priority from Events where Id = ?"; + my $deleteEventSth = $dbh->prepare_cached( $deleteEventSql ) or Fatal( "Can't prepare '$deleteEventSql': ".$dbh->errstr() ); + my $deleteFramesSql = "delete low_priority from Frames where EventId = ?"; + my $deleteFramesSth = $dbh->prepare_cached( $deleteFramesSql ) or Fatal( "Can't prepare '$deleteFramesSql': ".$dbh->errstr() ); + my $deleteStatsSql = "delete low_priority from Stats where EventId = ?"; + my $deleteStatsSth = $dbh->prepare_cached( $deleteStatsSql ) or Fatal( "Can't prepare '$deleteStatsSql': ".$dbh->errstr() ); + while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) + { + if ( my $fs_events = $fs_monitors->{$db_monitor} ) + { + if ( $db_events ) + { + while ( my ( $db_event, $age ) = each(%$db_events ) ) + { + if ( !defined($fs_events->{$db_event}) && ($age > MIN_AGE) ) + { + aud_print( "Database event '$db_monitor/$db_event' does not exist in filesystem" ); + if ( confirm() ) + { + my $res = $deleteEventSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $res = $deleteFramesSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteFramesSth->errstr() ); + $res = $deleteStatsSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteStatsSth->errstr() ); + $cleaned = 1; + } + } + } + } + } + else + { + #aud_print( "Database monitor '$db_monitor' does not exist in filesystem" ); + #if ( confirm() ) + #{ + # We don't actually do this in case it's new + #my $res = $deleteMonitorSth->execute( $db_monitor ) or Fatal( "Can't execute: ".$deleteMonitorSth->errstr() ); + #$cleaned = 1; + #} + } + } + redo MAIN if ( $cleaned ); + + # Remove orphaned events (with no monitor) + $cleaned = 0; + my $selectOrphanedEventsSql = "select Events.Id, Events.Name from Events left join Monitors on (Events.MonitorId = Monitors.Id) where isnull(Monitors.Id)"; + my $selectOrphanedEventsSth = $dbh->prepare_cached( $selectOrphanedEventsSql ) or Fatal( "Can't prepare '$selectOrphanedEventsSql': ".$dbh->errstr() ); + $res = $selectOrphanedEventsSth->execute() or Fatal( "Can't execute: ".$selectOrphanedEventsSth->errstr() ); + while( my $event = $selectOrphanedEventsSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned event with no monitor '$event->{Id}'" ); + if ( confirm() ) + { + $res = $deleteEventSth->execute( $event->{Id} ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedEventsSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove empty events (with no frames) + $cleaned = 0; + my $selectEmptyEventsSql = "select * from Events as E left join Frames as F on (E.Id = F.EventId) where isnull(F.EventId) and now() - interval ".MIN_AGE." second > E.StartTime"; + my $selectEmptyEventsSth = $dbh->prepare_cached( $selectEmptyEventsSql ) or Fatal( "Can't prepare '$selectEmptyEventsSql': ".$dbh->errstr() ); + $res = $selectEmptyEventsSth->execute() or Fatal( "Can't execute: ".$selectEmptyEventsSth->errstr() ); + while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) + { + aud_print( "Found empty event with no frame records '$event->{Id}'" ); + if ( confirm() ) + { + $res = $deleteEventSth->execute( $event->{Id} ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $cleaned = 1; + } + } + $selectEmptyEventsSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove orphaned frame records + $cleaned = 0; + my $selectOrphanedFramesSql = "select distinct EventId from Frames where EventId not in (select Id from Events)"; + my $selectOrphanedFramesSth = $dbh->prepare_cached( $selectOrphanedFramesSql ) or Fatal( "Can't prepare '$selectOrphanedFramesSql': ".$dbh->errstr() ); + $res = $selectOrphanedFramesSth->execute() or Fatal( "Can't execute: ".$selectOrphanedFramesSth->errstr() ); + while( my $frame = $selectOrphanedFramesSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned frame records for event '$frame->{EventId}'" ); + if ( confirm() ) + { + $res = $deleteFramesSth->execute( $frame->{EventId} ) or Fatal( "Can't execute: ".$deleteFramesSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedFramesSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove orphaned stats records + $cleaned = 0; + my $selectOrphanedStatsSql = "select distinct EventId from Stats where EventId not in (select Id from Events)"; + my $selectOrphanedStatsSth = $dbh->prepare_cached( $selectOrphanedStatsSql ) or Fatal( "Can't prepare '$selectOrphanedStatsSql': ".$dbh->errstr() ); + $res = $selectOrphanedStatsSth->execute() or Fatal( "Can't execute: ".$selectOrphanedStatsSth->errstr() ); + while( my $stat = $selectOrphanedStatsSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned statistic records for event '$stat->{EventId}'" ); + if ( confirm() ) + { + $res = $deleteStatsSth->execute( $stat->{EventId} ) or Fatal( "Can't execute: ".$deleteStatsSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedStatsSth->finish(); + redo MAIN if ( $cleaned ); + + # New audit to close any events that were left open for longer than MIN_AGE seconds + my $selectUnclosedEventsSql = "select E.Id, max(F.TimeStamp) as EndTime, unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length, max(F.FrameId) as Frames, count(if(F.Score>0,1,NULL)) as AlarmFrames, sum(F.Score) as TotScore, max(F.Score) as MaxScore, M.EventPrefix as Prefix from Events as E left join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where isnull(E.Frames) or isnull(E.EndTime) group by E.Id having EndTime < (now() - interval ".MIN_AGE." second)"; + my $selectUnclosedEventsSth = $dbh->prepare_cached( $selectUnclosedEventsSql ) or Fatal( "Can't prepare '$selectUnclosedEventsSql': ".$dbh->errstr() ); + my $updateUnclosedEventsSql = "update low_priority Events set Name = ?, EndTime = ?, Length = ?, Frames = ?, AlarmFrames = ?, TotScore = ?, AvgScore = ?, MaxScore = ?, Notes = concat_ws( ' ', Notes, ? ) where Id = ?"; + my $updateUnclosedEventsSth = $dbh->prepare_cached( $updateUnclosedEventsSql ) or Fatal( "Can't prepare '$updateUnclosedEventsSql': ".$dbh->errstr() ); + $res = $selectUnclosedEventsSth->execute() or Fatal( "Can't execute: ".$selectUnclosedEventsSth->errstr() ); + while( my $event = $selectUnclosedEventsSth->fetchrow_hashref() ) + { + aud_print( "Found open event '$event->{Id}'" ); + if ( confirm( 'close', 'closing' ) ) + { + $res = $updateUnclosedEventsSth->execute( sprintf( "%s%d%s", $event->{Prefix}, $event->{Id}, RECOVER_TAG ), $event->{EndTime}, $event->{Length}, $event->{Frames}, $event->{AlarmFrames}, $event->{TotScore}, $event->{AlarmFrames}?int($event->{TotScore}/$event->{AlarmFrames}):0, $event->{MaxScore}, RECOVER_TEXT, $event->{Id} ) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() ); + } + } + $selectUnclosedEventsSth->finish(); + + # Now delete any old image files + if ( my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}> ) + { + aud_print( "Deleting ".int(@old_files)." old images\n" ); + my $untainted_old_files = join( ";", @old_files ); + ( $untainted_old_files ) = ( $untainted_old_files =~ /^(.*)$/ ); + unlink( split( /;/, $untainted_old_files ) ); + } + + # Now delete any old swap files + ( my $swap_image_root ) = ( $swap_image_path =~ /^(.*)$/ ); # De-taint + File::Find::find( { wanted=>\&deleteSwapImage, untaint=>1 }, $swap_image_root ); + + # Prune the Logs table if required + if ( ZM_LOG_DATABASE_LIMIT ) + { + if ( ZM_LOG_DATABASE_LIMIT =~ /^\d+$/ ) + { + # Number of rows + my $selectLogRowCountSql = "select count(*) as Rows from Logs"; + my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql ) or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() ); + $res = $selectLogRowCountSth->execute() or Fatal( "Can't execute: ".$selectLogRowCountSth->errstr() ); + my $row = $selectLogRowCountSth->fetchrow_hashref(); + my $logRows = $row->{Rows}; + $selectLogRowCountSth->finish(); + if ( $logRows > ZM_LOG_DATABASE_LIMIT ) + { + my $deleteLogByRowsSql = "delete low_priority from Logs order by TimeKey asc limit ?"; + my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql ) or Fatal( "Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr() ); + $res = $deleteLogByRowsSth->execute( $logRows - ZM_LOG_DATABASE_LIMIT ) or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() ); + aud_print( "Deleted ".$deleteLogByRowsSth->rows()." log table entries by count\n" ) if ( $deleteLogByRowsSth->rows() ); + } + } + else + { + # Time of record + my $deleteLogByTimeSql = "delete low_priority from Logs where TimeKey < unix_timestamp(now() - interval ".ZM_LOG_DATABASE_LIMIT.")"; + my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql ) or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() ); + $res = $deleteLogByTimeSth->execute() or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() ); + aud_print( "Deleted ".$deleteLogByTimeSth->rows()." log table entries by time\n" ) if ( $deleteLogByTimeSth->rows() ); + } + } + $loop = $continuous; + + sleep( ZM_AUDIT_CHECK_INTERVAL ) if ( $continuous ); +}; + +exit( 0 ); + +sub aud_print( $ ) +{ + my $string = shift; + if ( !$continuous ) + { + print( $string ); + } + else + { + Info( $string ); + } +} + +sub confirm( ;$$ ) +{ + my $prompt = shift || "delete"; + my $action = shift || "deleting"; + + my $yesno = 0; + if ( $report ) + { + print( "\n" ); + } + elsif ( $interactive ) + { + print( ", $prompt y/n: " ); + my $char = <>; + chomp( $char ); + if ( $char eq 'q' ) + { + exit( 0 ); + } + if ( !$char ) + { + $char = 'y'; + } + $yesno = ( $char =~ /[yY]/ ); + } + else + { + if ( !$continuous ) + { + print( ", $action\n" ); + } + else + { + Info( $action ); + } + $yesno = 1; + } + return( $yesno ); +} + +sub deleteSwapImage() +{ + my $file = $_; + + if ( $file !~ /^zmswap-/ ) + { + return; + } + + # Ignore directories + if ( -d $file ) + { + return; + } + + if ( -M $file > $max_swap_age ) + { + Debug( "Deleting $file" ); + #unlink( $file ); + } +} diff --git a/scripts/zmaudit.pl.in b/scripts/zmaudit.pl.in new file mode 100644 index 000000000..955198c9f --- /dev/null +++ b/scripts/zmaudit.pl.in @@ -0,0 +1,510 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Audit Script, $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 script checks for consistency between the event filesystem and +# the database. If events are found in one and not the other they are +# deleted (optionally). Additionally any monitor event directories that +# do not correspond to a database monitor are similarly disposed of. +# However monitors in the database that don't have a directory are left +# alone as this is valid if they are newly created and have no events +# yet. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant MIN_AGE => 300; # Minimum age when we will delete anything +use constant MAX_AGED_DIRS => 10; # Number of event dirs to check age on +use constant RECOVER_TAG => "(r)"; # Tag to append to event name when recovered +use constant RECOVER_TEXT => "Recovered."; # Text to append to event notes when recovered + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use DBI; +use POSIX; +use File::Find; +use Time::HiRes qw/gettimeofday/; +use Getopt::Long; + +use constant IMAGE_PATH => ZM_PATH_WEB.'/'.ZM_DIR_IMAGES; +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $report = 0; +my $interactive = 0; +my $continuous = 0; + +sub usage +{ + print( " +Usage: zmaudit.pl [-r,-report|-i,-interactive] +Parameters are :- +-r, --report - Just report don't actually do anything +-i, --interactive - Ask before applying any changes +-c, --continuous - Run continuously +"); + exit( -1 ); +} + +sub aud_print( $ ); +sub confirm( ;$$ ); +sub deleteSwapImage(); + +logInit(); +logSetSignal(); + +if ( !GetOptions( 'report'=>\$report, 'interactive'=>\$interactive, 'continuous'=>\$continuous ) ) +{ + usage(); +} + +if ( ($report + $interactive + $continuous) > 1 ) +{ + print( STDERR "Error, only option may be specified\n" ); + usage(); +} + +my $dbh = zmDbConnect(); + +chdir( EVENT_PATH ); + +my $max_image_age = 6/24; # 6 hours +my $max_swap_age = 24/24; # 24 hours +my $image_path = IMAGE_PATH; +my $swap_image_path = ZM_PATH_SWAP; + +my $loop = 1; +my $cleaned = 0; +MAIN: while( $loop ) +{ + my $db_monitors; + my $monitorSelectSql = "select Id from Monitors order by Id"; + my $monitorSelectSth = $dbh->prepare_cached( $monitorSelectSql ) or Fatal( "Can't prepare '$monitorSelectSql': ".$dbh->errstr() ); + my $eventSelectSql = "select Id, (unix_timestamp() - unix_timestamp(StartTime)) as Age from Events where MonitorId = ? order by Id"; + my $eventSelectSth = $dbh->prepare_cached( $eventSelectSql ) or Fatal( "Can't prepare '$eventSelectSql': ".$dbh->errstr() ); + + $cleaned = 0; + my $res = $monitorSelectSth->execute() or Fatal( "Can't execute: ".$monitorSelectSth->errstr() ); + while( my $monitor = $monitorSelectSth->fetchrow_hashref() ) + { + Debug( "Found database monitor '$monitor->{Id}'" ); + my $db_events = $db_monitors->{$monitor->{Id}} = {}; + my $res = $eventSelectSth->execute( $monitor->{Id} ) or Fatal( "Can't execute: ".$eventSelectSth->errstr() ); + while ( my $event = $eventSelectSth->fetchrow_hashref() ) + { + $db_events->{$event->{Id}} = $event->{Age}; + } + Debug( "Got ".int(keys(%$db_events))." events\n" ); + $eventSelectSth->finish(); + } + $monitorSelectSth->finish(); + + my $fs_monitors; + foreach my $monitor ( <[0-9]*> ) + { + Debug( "Found filesystem monitor '$monitor'" ); + my $fs_events = $fs_monitors->{$monitor} = {}; + ( my $monitor_dir ) = ( $monitor =~ /^(.*)$/ ); # De-taint + + if ( ZM_USE_DEEP_STORAGE ) + { + foreach my $day_dir ( <$monitor_dir/*/*/*> ) + { + Debug( "Checking $day_dir" ); + ( $day_dir ) = ( $day_dir =~ /^(.*)$/ ); # De-taint + chdir( $day_dir ); + opendir( DIR, "." ) or Fatal( "Can't open directory '$day_dir': $!" ); + my @event_links = sort { $b <=> $a } grep { -l $_ } readdir( DIR ); + closedir( DIR ); + my $count = 0; + foreach my $event_link ( @event_links ) + { + Debug( "Checking link $event_link" ); + ( my $event = $event_link ) =~ s/^.*\.//; + my $event_path = readlink( $event_link ); + if ( $count++ > MAX_AGED_DIRS ) + { + $fs_events->{$event} = -1; + } + else + { + if ( !-e $event_path ) + { + aud_print( "Event link $day_dir/$event_link does not point to valid target" ); + if ( confirm() ) + { + ( $event_link ) = ( $event_link =~ /^(.*)$/ ); # De-taint + unlink( $event_link ); + $cleaned = 1; + } + } + else + { + $fs_events->{$event} = (time() - ($^T - ((-M $event_path) * 24*60*60))); + } + } + } + chdir( EVENT_PATH ); + } + } + else + { + chdir( $monitor_dir ); + opendir( DIR, "." ) or Fatal( "Can't open directory '$monitor_dir': $!" ); + my @temp_events = sort { $b <=> $a } grep { -d $_ && $_ =~ /^\d+$/ } readdir( DIR ); + closedir( DIR ); + my $count = 0; + foreach my $event ( @temp_events ) + { + if ( $count++ > MAX_AGED_DIRS ) + { + $fs_events->{$event} = -1; + } + else + { + $fs_events->{$event} = (time() - ($^T - ((-M $event) * 24*60*60))); + } + } + chdir( EVENT_PATH ); + } + Debug( "Got ".int(keys(%$fs_events))." events\n" ); + } + redo MAIN if ( $cleaned ); + + $cleaned = 0; + while ( my ( $fs_monitor, $fs_events ) = each(%$fs_monitors) ) + { + if ( my $db_events = $db_monitors->{$fs_monitor} ) + { + if ( $fs_events ) + { + while ( my ( $fs_event, $age ) = each(%$fs_events ) ) + { + if ( !defined($db_events->{$fs_event}) && ($age < 0 || ($age > MIN_AGE)) ) + { + aud_print( "Filesystem event '$fs_monitor/$fs_event' does not exist in database" ); + if ( confirm() ) + { + deleteEventFiles( $fs_event, $fs_monitor ); + $cleaned = 1; + } + } + } + } + } + else + { + aud_print( "Filesystem monitor '$fs_monitor' does not exist in database" ); + if ( confirm() ) + { + my $command = "rm -rf $fs_monitor"; + executeShellCommand( $command ); + $cleaned = 1; + } + } + } + + my $monitor_links; + foreach my $link ( <*> ) + { + next if ( !-l $link ); + next if ( -e $link ); + + aud_print( "Filesystem monitor link '$link' does not point to valid monitor directory" ); + if ( confirm() ) + { + ( $link ) = ( $link =~ /^(.*)$/ ); # De-taint + my $command = "rm $link"; + executeShellCommand( $command ); + $cleaned = 1; + } + } + redo MAIN if ( $cleaned ); + + $cleaned = 0; + my $deleteMonitorSql = "delete low_priority from Monitors where Id = ?"; + my $deleteMonitorSth = $dbh->prepare_cached( $deleteMonitorSql ) or Fatal( "Can't prepare '$deleteMonitorSql': ".$dbh->errstr() ); + my $deleteEventSql = "delete low_priority from Events where Id = ?"; + my $deleteEventSth = $dbh->prepare_cached( $deleteEventSql ) or Fatal( "Can't prepare '$deleteEventSql': ".$dbh->errstr() ); + my $deleteFramesSql = "delete low_priority from Frames where EventId = ?"; + my $deleteFramesSth = $dbh->prepare_cached( $deleteFramesSql ) or Fatal( "Can't prepare '$deleteFramesSql': ".$dbh->errstr() ); + my $deleteStatsSql = "delete low_priority from Stats where EventId = ?"; + my $deleteStatsSth = $dbh->prepare_cached( $deleteStatsSql ) or Fatal( "Can't prepare '$deleteStatsSql': ".$dbh->errstr() ); + while ( my ( $db_monitor, $db_events ) = each(%$db_monitors) ) + { + if ( my $fs_events = $fs_monitors->{$db_monitor} ) + { + if ( $db_events ) + { + while ( my ( $db_event, $age ) = each(%$db_events ) ) + { + if ( !defined($fs_events->{$db_event}) && ($age > MIN_AGE) ) + { + aud_print( "Database event '$db_monitor/$db_event' does not exist in filesystem" ); + if ( confirm() ) + { + my $res = $deleteEventSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $res = $deleteFramesSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteFramesSth->errstr() ); + $res = $deleteStatsSth->execute( $db_event ) or Fatal( "Can't execute: ".$deleteStatsSth->errstr() ); + $cleaned = 1; + } + } + } + } + } + else + { + #aud_print( "Database monitor '$db_monitor' does not exist in filesystem" ); + #if ( confirm() ) + #{ + # We don't actually do this in case it's new + #my $res = $deleteMonitorSth->execute( $db_monitor ) or Fatal( "Can't execute: ".$deleteMonitorSth->errstr() ); + #$cleaned = 1; + #} + } + } + redo MAIN if ( $cleaned ); + + # Remove orphaned events (with no monitor) + $cleaned = 0; + my $selectOrphanedEventsSql = "select Events.Id, Events.Name from Events left join Monitors on (Events.MonitorId = Monitors.Id) where isnull(Monitors.Id)"; + my $selectOrphanedEventsSth = $dbh->prepare_cached( $selectOrphanedEventsSql ) or Fatal( "Can't prepare '$selectOrphanedEventsSql': ".$dbh->errstr() ); + $res = $selectOrphanedEventsSth->execute() or Fatal( "Can't execute: ".$selectOrphanedEventsSth->errstr() ); + while( my $event = $selectOrphanedEventsSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned event with no monitor '$event->{Id}'" ); + if ( confirm() ) + { + $res = $deleteEventSth->execute( $event->{Id} ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedEventsSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove empty events (with no frames) + $cleaned = 0; + my $selectEmptyEventsSql = "select * from Events as E left join Frames as F on (E.Id = F.EventId) where isnull(F.EventId) and now() - interval ".MIN_AGE." second > E.StartTime"; + my $selectEmptyEventsSth = $dbh->prepare_cached( $selectEmptyEventsSql ) or Fatal( "Can't prepare '$selectEmptyEventsSql': ".$dbh->errstr() ); + $res = $selectEmptyEventsSth->execute() or Fatal( "Can't execute: ".$selectEmptyEventsSth->errstr() ); + while( my $event = $selectEmptyEventsSth->fetchrow_hashref() ) + { + aud_print( "Found empty event with no frame records '$event->{Id}'" ); + if ( confirm() ) + { + $res = $deleteEventSth->execute( $event->{Id} ) or Fatal( "Can't execute: ".$deleteEventSth->errstr() ); + $cleaned = 1; + } + } + $selectEmptyEventsSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove orphaned frame records + $cleaned = 0; + my $selectOrphanedFramesSql = "select distinct EventId from Frames where EventId not in (select Id from Events)"; + my $selectOrphanedFramesSth = $dbh->prepare_cached( $selectOrphanedFramesSql ) or Fatal( "Can't prepare '$selectOrphanedFramesSql': ".$dbh->errstr() ); + $res = $selectOrphanedFramesSth->execute() or Fatal( "Can't execute: ".$selectOrphanedFramesSth->errstr() ); + while( my $frame = $selectOrphanedFramesSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned frame records for event '$frame->{EventId}'" ); + if ( confirm() ) + { + $res = $deleteFramesSth->execute( $frame->{EventId} ) or Fatal( "Can't execute: ".$deleteFramesSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedFramesSth->finish(); + redo MAIN if ( $cleaned ); + + # Remove orphaned stats records + $cleaned = 0; + my $selectOrphanedStatsSql = "select distinct EventId from Stats where EventId not in (select Id from Events)"; + my $selectOrphanedStatsSth = $dbh->prepare_cached( $selectOrphanedStatsSql ) or Fatal( "Can't prepare '$selectOrphanedStatsSql': ".$dbh->errstr() ); + $res = $selectOrphanedStatsSth->execute() or Fatal( "Can't execute: ".$selectOrphanedStatsSth->errstr() ); + while( my $stat = $selectOrphanedStatsSth->fetchrow_hashref() ) + { + aud_print( "Found orphaned statistic records for event '$stat->{EventId}'" ); + if ( confirm() ) + { + $res = $deleteStatsSth->execute( $stat->{EventId} ) or Fatal( "Can't execute: ".$deleteStatsSth->errstr() ); + $cleaned = 1; + } + } + $selectOrphanedStatsSth->finish(); + redo MAIN if ( $cleaned ); + + # New audit to close any events that were left open for longer than MIN_AGE seconds + my $selectUnclosedEventsSql = "select E.Id, max(F.TimeStamp) as EndTime, unix_timestamp(max(F.TimeStamp)) - unix_timestamp(E.StartTime) as Length, max(F.FrameId) as Frames, count(if(F.Score>0,1,NULL)) as AlarmFrames, sum(F.Score) as TotScore, max(F.Score) as MaxScore, M.EventPrefix as Prefix from Events as E left join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where isnull(E.Frames) or isnull(E.EndTime) group by E.Id having EndTime < (now() - interval ".MIN_AGE." second)"; + my $selectUnclosedEventsSth = $dbh->prepare_cached( $selectUnclosedEventsSql ) or Fatal( "Can't prepare '$selectUnclosedEventsSql': ".$dbh->errstr() ); + my $updateUnclosedEventsSql = "update low_priority Events set Name = ?, EndTime = ?, Length = ?, Frames = ?, AlarmFrames = ?, TotScore = ?, AvgScore = ?, MaxScore = ?, Notes = concat_ws( ' ', Notes, ? ) where Id = ?"; + my $updateUnclosedEventsSth = $dbh->prepare_cached( $updateUnclosedEventsSql ) or Fatal( "Can't prepare '$updateUnclosedEventsSql': ".$dbh->errstr() ); + $res = $selectUnclosedEventsSth->execute() or Fatal( "Can't execute: ".$selectUnclosedEventsSth->errstr() ); + while( my $event = $selectUnclosedEventsSth->fetchrow_hashref() ) + { + aud_print( "Found open event '$event->{Id}'" ); + if ( confirm( 'close', 'closing' ) ) + { + $res = $updateUnclosedEventsSth->execute( sprintf( "%s%d%s", $event->{Prefix}, $event->{Id}, RECOVER_TAG ), $event->{EndTime}, $event->{Length}, $event->{Frames}, $event->{AlarmFrames}, $event->{TotScore}, $event->{AlarmFrames}?int($event->{TotScore}/$event->{AlarmFrames}):0, $event->{MaxScore}, RECOVER_TEXT, $event->{Id} ) or Fatal( "Can't execute: ".$updateUnclosedEventsSth->errstr() ); + } + } + $selectUnclosedEventsSth->finish(); + + # Now delete any old image files + if ( my @old_files = grep { -M > $max_image_age } <$image_path/*.{jpg,gif,wbmp}> ) + { + aud_print( "Deleting ".int(@old_files)." old images\n" ); + my $untainted_old_files = join( ";", @old_files ); + ( $untainted_old_files ) = ( $untainted_old_files =~ /^(.*)$/ ); + unlink( split( /;/, $untainted_old_files ) ); + } + + # Now delete any old swap files + ( my $swap_image_root ) = ( $swap_image_path =~ /^(.*)$/ ); # De-taint + File::Find::find( { wanted=>\&deleteSwapImage, untaint=>1 }, $swap_image_root ); + + # Prune the Logs table if required + if ( ZM_LOG_DATABASE_LIMIT ) + { + if ( ZM_LOG_DATABASE_LIMIT =~ /^\d+$/ ) + { + # Number of rows + my $selectLogRowCountSql = "select count(*) as Rows from Logs"; + my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql ) or Fatal( "Can't prepare '$selectLogRowCountSql': ".$dbh->errstr() ); + $res = $selectLogRowCountSth->execute() or Fatal( "Can't execute: ".$selectLogRowCountSth->errstr() ); + my $row = $selectLogRowCountSth->fetchrow_hashref(); + my $logRows = $row->{Rows}; + $selectLogRowCountSth->finish(); + if ( $logRows > ZM_LOG_DATABASE_LIMIT ) + { + my $deleteLogByRowsSql = "delete low_priority from Logs order by TimeKey asc limit ?"; + my $deleteLogByRowsSth = $dbh->prepare_cached( $deleteLogByRowsSql ) or Fatal( "Can't prepare '$deleteLogByRowsSql': ".$dbh->errstr() ); + $res = $deleteLogByRowsSth->execute( $logRows - ZM_LOG_DATABASE_LIMIT ) or Fatal( "Can't execute: ".$deleteLogByRowsSth->errstr() ); + aud_print( "Deleted ".$deleteLogByRowsSth->rows()." log table entries by count\n" ) if ( $deleteLogByRowsSth->rows() ); + } + } + else + { + # Time of record + my $deleteLogByTimeSql = "delete low_priority from Logs where TimeKey < unix_timestamp(now() - interval ".ZM_LOG_DATABASE_LIMIT.")"; + my $deleteLogByTimeSth = $dbh->prepare_cached( $deleteLogByTimeSql ) or Fatal( "Can't prepare '$deleteLogByTimeSql': ".$dbh->errstr() ); + $res = $deleteLogByTimeSth->execute() or Fatal( "Can't execute: ".$deleteLogByTimeSth->errstr() ); + aud_print( "Deleted ".$deleteLogByTimeSth->rows()." log table entries by time\n" ) if ( $deleteLogByTimeSth->rows() ); + } + } + $loop = $continuous; + + sleep( ZM_AUDIT_CHECK_INTERVAL ) if ( $continuous ); +}; + +exit( 0 ); + +sub aud_print( $ ) +{ + my $string = shift; + if ( !$continuous ) + { + print( $string ); + } + else + { + Info( $string ); + } +} + +sub confirm( ;$$ ) +{ + my $prompt = shift || "delete"; + my $action = shift || "deleting"; + + my $yesno = 0; + if ( $report ) + { + print( "\n" ); + } + elsif ( $interactive ) + { + print( ", $prompt y/n: " ); + my $char = <>; + chomp( $char ); + if ( $char eq 'q' ) + { + exit( 0 ); + } + if ( !$char ) + { + $char = 'y'; + } + $yesno = ( $char =~ /[yY]/ ); + } + else + { + if ( !$continuous ) + { + print( ", $action\n" ); + } + else + { + Info( $action ); + } + $yesno = 1; + } + return( $yesno ); +} + +sub deleteSwapImage() +{ + my $file = $_; + + if ( $file !~ /^zmswap-/ ) + { + return; + } + + # Ignore directories + if ( -d $file ) + { + return; + } + + if ( -M $file > $max_swap_age ) + { + Debug( "Deleting $file" ); + #unlink( $file ); + } +} diff --git a/scripts/zmcontrol.pl b/scripts/zmcontrol.pl new file mode 100644 index 000000000..d71da2084 --- /dev/null +++ b/scripts/zmcontrol.pl @@ -0,0 +1,237 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Control Script, $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 script continuously monitors the recorded events for the given +# monitor and applies any filters which would delete and/or upload +# matching events +# +use strict; + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use Getopt::Long; +use POSIX qw/strftime EPIPE/; +use Socket; +use Data::Dumper; +use Module::Load; + +use constant MAX_CONNECT_DELAY => 10; +use constant MAX_COMMAND_WAIT => 1800; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmcontrol.pl --id --command= +"); + exit( -1 ); +} + +logInit(); + +my $arg_string = join( " ", @ARGV ); + +my $id; +my %options; + +if ( !GetOptions( + 'id=i'=>\$id, + 'command=s'=>\$options{command}, + 'xcoord=i'=>\$options{xcoord}, + 'ycoord=i'=>\$options{ycoord}, + 'speed=i'=>\$options{speed}, + 'step=i'=>\$options{step}, + 'panspeed=i'=>\$options{panspeed}, + 'tiltspeed=i'=>\$options{tiltspeed}, + 'panstep=i'=>\$options{panstep}, + 'tiltstep=i'=>\$options{tiltstep}, + 'preset=i'=>\$options{preset}, + 'autostop'=>\$options{autostop}, + ) +) +{ + Usage(); +} + +if ( !$id || !$options{command} ) +{ + print( STDERR "Please give a valid monitor id and command\n" ); + Usage(); +} + +( $id ) = $id =~ /^(\w+)$/; + +Debug( $arg_string ); + +my $sock_file = ZM_PATH_SOCKS.'/zmcontrol-'.$id.'.sock'; + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( $sock_file ); +my $server_up = connect( CLIENT, $saddr ); +if ( !$server_up ) +{ + # The server isn't there + my $monitor = zmDbGetMonitorAndControl( $id ); + if ( !$monitor ) + { + Fatal( "Unable to load control data for monitor $id" ); + } + my $protocol = $monitor->{Protocol}; + + if ( -x $protocol ) + { + # Protocol is actually a script! + # Holdover from previous versions + my $command .= $protocol.' '.$arg_string; + Debug( $command."\n" ); + + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Command '$command' exited with status: $status\n" ); + exit( $status ); + } + exit( 0 ); + } + + Info( "Starting control server $id/$protocol" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + logReinit(); + + # Parent process just sleep and fall through + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" ); + my $attempts = 0; + while (!connect( CLIENT, $saddr )) + { + $attempts++; + Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY); + sleep(1); + } + } + elsif ( defined($cpid) ) + { + close( STDOUT ); + close( STDERR ); + + setpgrp(); + + logReinit(); + + Info( "Control server $id/$protocol starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() ) ); + + $0 = $0." --id $id"; + + load "ZoneMinder::Control::$protocol"; + + my $control = "ZoneMinder::Control::$protocol"->new( $id ); + my $control_key = $control->getKey(); + $control->loadMonitor(); + + $control->open(); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( $sock_file ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + my $rin = ''; + vec( $rin, fileno(SERVER), 1 ) = 1; + my $win = $rin; + my $ein = $win; + my $timeout = MAX_COMMAND_WAIT; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER), 1 ) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + next if ( !$message ); + + my $params = jsonDecode( $message ); + #Debug( Dumper( $params ) ); + + my $command = $params->{command}; + $control->$command( $params ); + close( CLIENT ); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EPIPE ) + { + Error( "Can't select: $!" ); + } + else + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + last; + } + } + Info( "Control server $id/$protocol exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() ) ); + unlink( $sock_file ); + $control->close(); + exit( 0 ); + } + else + { + Fatal( "Can't fork: $!" ); + } +} + +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); + +my $message = jsonEncode( \%options ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); + +exit( 0 ); diff --git a/scripts/zmcontrol.pl.in b/scripts/zmcontrol.pl.in new file mode 100644 index 000000000..aba203614 --- /dev/null +++ b/scripts/zmcontrol.pl.in @@ -0,0 +1,237 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Control Script, $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 script continuously monitors the recorded events for the given +# monitor and applies any filters which would delete and/or upload +# matching events +# +use strict; + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use Getopt::Long; +use POSIX qw/strftime EPIPE/; +use Socket; +use Data::Dumper; +use Module::Load; + +use constant MAX_CONNECT_DELAY => 10; +use constant MAX_COMMAND_WAIT => 1800; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmcontrol.pl --id --command= +"); + exit( -1 ); +} + +logInit(); + +my $arg_string = join( " ", @ARGV ); + +my $id; +my %options; + +if ( !GetOptions( + 'id=i'=>\$id, + 'command=s'=>\$options{command}, + 'xcoord=i'=>\$options{xcoord}, + 'ycoord=i'=>\$options{ycoord}, + 'speed=i'=>\$options{speed}, + 'step=i'=>\$options{step}, + 'panspeed=i'=>\$options{panspeed}, + 'tiltspeed=i'=>\$options{tiltspeed}, + 'panstep=i'=>\$options{panstep}, + 'tiltstep=i'=>\$options{tiltstep}, + 'preset=i'=>\$options{preset}, + 'autostop'=>\$options{autostop}, + ) +) +{ + Usage(); +} + +if ( !$id || !$options{command} ) +{ + print( STDERR "Please give a valid monitor id and command\n" ); + Usage(); +} + +( $id ) = $id =~ /^(\w+)$/; + +Debug( $arg_string ); + +my $sock_file = ZM_PATH_SOCKS.'/zmcontrol-'.$id.'.sock'; + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( $sock_file ); +my $server_up = connect( CLIENT, $saddr ); +if ( !$server_up ) +{ + # The server isn't there + my $monitor = zmDbGetMonitorAndControl( $id ); + if ( !$monitor ) + { + Fatal( "Unable to load control data for monitor $id" ); + } + my $protocol = $monitor->{Protocol}; + + if ( -x $protocol ) + { + # Protocol is actually a script! + # Holdover from previous versions + my $command .= $protocol.' '.$arg_string; + Debug( $command."\n" ); + + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Command '$command' exited with status: $status\n" ); + exit( $status ); + } + exit( 0 ); + } + + Info( "Starting control server $id/$protocol" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + logReinit(); + + # Parent process just sleep and fall through + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or die( "Can't open socket: $!" ); + my $attempts = 0; + while (!connect( CLIENT, $saddr )) + { + $attempts++; + Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY); + sleep(1); + } + } + elsif ( defined($cpid) ) + { + close( STDOUT ); + close( STDERR ); + + setpgrp(); + + logReinit(); + + Info( "Control server $id/$protocol starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() ) ); + + $0 = $0." --id $id"; + + load "ZoneMinder::Control::$protocol"; + + my $control = "ZoneMinder::Control::$protocol"->new( $id ); + my $control_key = $control->getKey(); + $control->loadMonitor(); + + $control->open(); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( $sock_file ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + my $rin = ''; + vec( $rin, fileno(SERVER), 1 ) = 1; + my $win = $rin; + my $ein = $win; + my $timeout = MAX_COMMAND_WAIT; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER), 1 ) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + next if ( !$message ); + + my $params = jsonDecode( $message ); + #Debug( Dumper( $params ) ); + + my $command = $params->{command}; + $control->$command( $params ); + close( CLIENT ); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EPIPE ) + { + Error( "Can't select: $!" ); + } + else + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + last; + } + } + Info( "Control server $id/$protocol exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() ) ); + unlink( $sock_file ); + $control->close(); + exit( 0 ); + } + else + { + Fatal( "Can't fork: $!" ); + } +} + +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); + +my $message = jsonEncode( \%options ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); + +exit( 0 ); diff --git a/scripts/zmdbbackup b/scripts/zmdbbackup new file mode 100644 index 000000000..f98439f20 --- /dev/null +++ b/scripts/zmdbbackup @@ -0,0 +1,37 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmdbbackup +# +# USAGE: ./zmdbbackup +# +# DESCRIPTION: Uses mysqldump to backup the config info in the zm DB +# OPTIONS: --- None +# REQUIREMENTS: --- mysqldump +# BUGS: --- +# NOTES: --- +# AUTHOR: Ross Melin +# COMPANY: +# VERSION: 2.0 +# CREATED: 05/26/2006 06:21:00 AM PDT +# REVISION: --- +#=============================================================================== + +# Edit these to suit your configuration +ZM_CONFIG=/etc/zm/zm.conf +source $ZM_CONFIG + +MYSQLDUMP=/usr/bin/mysqldump +BACKUP_PATH=/var/lib/zm +BACKUP_FILE=zm_backup.sql +DUMPOPTS="--user=$ZM_DB_USER --password=$ZM_DB_PASS --opt" +TABLES="Config Filters Groups Monitors States TriggersX10 Users Zones" +OUTFILE="$BACKUP_PATH/$BACKUP_FILE" + +echo "-- +-- Created by zm_db_backup for ZoneMinder Version $ZM_VERSION +--" > $OUTFILE + +$MYSQLDUMP $DUMPOPTS zm $TABLES >> $OUTFILE + +exit 0 diff --git a/scripts/zmdbbackup.in b/scripts/zmdbbackup.in new file mode 100644 index 000000000..303cf86be --- /dev/null +++ b/scripts/zmdbbackup.in @@ -0,0 +1,37 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmdbbackup +# +# USAGE: ./zmdbbackup +# +# DESCRIPTION: Uses mysqldump to backup the config info in the zm DB +# OPTIONS: --- None +# REQUIREMENTS: --- mysqldump +# BUGS: --- +# NOTES: --- +# AUTHOR: Ross Melin +# COMPANY: +# VERSION: 2.0 +# CREATED: 05/26/2006 06:21:00 AM PDT +# REVISION: --- +#=============================================================================== + +# Edit these to suit your configuration +ZM_CONFIG=@ZM_CONFIG@ +source $ZM_CONFIG + +MYSQLDUMP=/usr/bin/mysqldump +BACKUP_PATH=/var/lib/zm +BACKUP_FILE=zm_backup.sql +DUMPOPTS="--user=$ZM_DB_USER --password=$ZM_DB_PASS --opt" +TABLES="Config Filters Groups Monitors States TriggersX10 Users Zones" +OUTFILE="$BACKUP_PATH/$BACKUP_FILE" + +echo "-- +-- Created by zm_db_backup for ZoneMinder Version $ZM_VERSION +--" > $OUTFILE + +$MYSQLDUMP $DUMPOPTS zm $TABLES >> $OUTFILE + +exit 0 diff --git a/scripts/zmdbrestore b/scripts/zmdbrestore new file mode 100644 index 000000000..68f17e887 --- /dev/null +++ b/scripts/zmdbrestore @@ -0,0 +1,172 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmdbrestore +# +# USAGE: ./zmdbrestore +# +# DESCRIPTION: Restore a ZoneMinder DB from a backup created by zm_db_backup +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: (), +# COMPANY: +# VERSION: 1.0 +# CREATED: 05/29/2006 04:45:06 PM PDT +# REVISION: --- +#=============================================================================== + +ZM_CONFIG=/etc/zm/zm.conf +ZM_BACKUP=/var/lib/zm/zm_backup.sql +EVENTS_DIR=events + +loadcfg() { + if [ -f $ZM_CONFIG ]; then + . $ZM_CONFIG + else + echo "ERROR: $ZM_CONFIG not found." + exit 1 + fi +} + +chkcfg(){ +for n in ZM_DB_HOST ZM_DB_NAME ZM_DB_USER ZM_DB_PASS; do + eval "val=\$$n" + if [ "$val" = "" ]; then + echo "ERROR($ZM_CONFIG): $n should not be empty." + echo "Enter a $n for ZM to use the Database." + if [ "$n" = "ZM_DB_PASS" ]; then + echo -n "Will not echo on screen $n : " + stty -echo # Turns off screen echo. + read newval + stty echo # Restores screen echo. + echo "" + ### The following can be used to generate a random password + # randstr newval 16 + else + echo -n "$n : " + read newval + fi + cp $ZM_CONFIG /tmp/$$ && + sed 's/^'$n='.*$/'$n=$newval'/g' /tmp/$$ >$ZM_CONFIG + + fi +done + + if [ "$ZM_DB_HOST" = "localhost" ] + then + ClientHost=localhost + else + ClientHost=`hostname` + fi +} + +reloadcfg(){ + loadcfg +} + +chk_backup_ver(){ + if + [ -e $ZM_BACKUP ] + then + BACKUP_VER=$(cat $ZM_BACKUP | head -n 2 |tail -n 1 |cut -f 8 -d " ") + else + echo "$ZM_BACKUP doesn't exist" + exit 1 + fi + + + if + [ $BACKUP_VER != $ZM_VERSION ] + then + echo "$ZM_BACKUP is from version $BACKUP_VER" + echo "ZoneMinder version is $ZM_VERSION" + exit 1 + fi +} + +getmylogin(){ + echo "Enter MySQL Administrator username" + echo "(Default: root and password is blank)" + echo -n "MySQL Admin: " + read MYADMIN + echo -n "Password: " + read MYPASS + if [ "X$MYPASS" != "X" ]; then MYPASS="-p$MYPASS"; fi + echo "\q" |mysql -u $MYADMIN $MYPASS || exit 0 + +} + +checkfordb(){ + + if + echo "show databases" |mysql -u $MYADMIN "$MYPASS" |grep zm + then + echo "A $ZM_DB_NAME database exists." + while [ true ] + do + echo "Choose one of the following options:" + echo "[D]rop the old database and reinitialize" + echo "[E]xit and do nothing" + read OPTION + case $OPTION in + "D"|"d") + echo "drop database zm;"|mysql -u $MYADMIN $MYPASS + return + ;; + "E"|"e") + exit 0 + ;; + esac + done + + fi +} + +initdb(){ + sql=/tmp/zm.crdb.sql + echo "" >$sql + chmod 600 $sql + + echo "CREATE DATABASE $ZM_DB_NAME;" >>$sql + echo "USE $ZM_DB_NAME;" >>$sql + + echo "GRANT all on $ZM_DB_NAME.* TO '$ZM_DB_USER'@'$ClientHost' IDENTIFIED BY '$ZM_DB_PASS';" >>$sql + + cat $sql | mysql -B -h $ZM_DB_HOST -u $MYADMIN $MYPASS + rm -f $sql + + cat $ZM_PATH_UPDATE/zm_create.sql | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + +} + +restoredb(){ + if + [ -e $ZM_BACKUP ] + then + cat $ZM_BACKUP | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + else + echo "$ZM_BACKUP doesn't exist" + exit 1 + fi +} + +restore_events(){ + for SQL in $(find $ZM_PATH_WEB/$EVENTS_DIR -name .sql) + do + cat $SQL | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + done +} + +loadcfg +chkcfg +reloadcfg +chk_backup_ver +getmylogin +checkfordb +initdb +restoredb +restore_events +exit 0 diff --git a/scripts/zmdbrestore.in b/scripts/zmdbrestore.in new file mode 100644 index 000000000..4cf8c0ffa --- /dev/null +++ b/scripts/zmdbrestore.in @@ -0,0 +1,172 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmdbrestore +# +# USAGE: ./zmdbrestore +# +# DESCRIPTION: Restore a ZoneMinder DB from a backup created by zm_db_backup +# +# OPTIONS: --- +# REQUIREMENTS: --- +# BUGS: --- +# NOTES: --- +# AUTHOR: (), +# COMPANY: +# VERSION: 1.0 +# CREATED: 05/29/2006 04:45:06 PM PDT +# REVISION: --- +#=============================================================================== + +ZM_CONFIG=@ZM_CONFIG@ +ZM_BACKUP=/var/lib/zm/zm_backup.sql +EVENTS_DIR=events + +loadcfg() { + if [ -f $ZM_CONFIG ]; then + . $ZM_CONFIG + else + echo "ERROR: $ZM_CONFIG not found." + exit 1 + fi +} + +chkcfg(){ +for n in ZM_DB_HOST ZM_DB_NAME ZM_DB_USER ZM_DB_PASS; do + eval "val=\$$n" + if [ "$val" = "" ]; then + echo "ERROR($ZM_CONFIG): $n should not be empty." + echo "Enter a $n for ZM to use the Database." + if [ "$n" = "ZM_DB_PASS" ]; then + echo -n "Will not echo on screen $n : " + stty -echo # Turns off screen echo. + read newval + stty echo # Restores screen echo. + echo "" + ### The following can be used to generate a random password + # randstr newval 16 + else + echo -n "$n : " + read newval + fi + cp $ZM_CONFIG /tmp/$$ && + sed 's/^'$n='.*$/'$n=$newval'/g' /tmp/$$ >$ZM_CONFIG + + fi +done + + if [ "$ZM_DB_HOST" = "localhost" ] + then + ClientHost=localhost + else + ClientHost=`hostname` + fi +} + +reloadcfg(){ + loadcfg +} + +chk_backup_ver(){ + if + [ -e $ZM_BACKUP ] + then + BACKUP_VER=$(cat $ZM_BACKUP | head -n 2 |tail -n 1 |cut -f 8 -d " ") + else + echo "$ZM_BACKUP doesn't exist" + exit 1 + fi + + + if + [ $BACKUP_VER != $ZM_VERSION ] + then + echo "$ZM_BACKUP is from version $BACKUP_VER" + echo "ZoneMinder version is $ZM_VERSION" + exit 1 + fi +} + +getmylogin(){ + echo "Enter MySQL Administrator username" + echo "(Default: root and password is blank)" + echo -n "MySQL Admin: " + read MYADMIN + echo -n "Password: " + read MYPASS + if [ "X$MYPASS" != "X" ]; then MYPASS="-p$MYPASS"; fi + echo "\q" |mysql -u $MYADMIN $MYPASS || exit 0 + +} + +checkfordb(){ + + if + echo "show databases" |mysql -u $MYADMIN "$MYPASS" |grep zm + then + echo "A $ZM_DB_NAME database exists." + while [ true ] + do + echo "Choose one of the following options:" + echo "[D]rop the old database and reinitialize" + echo "[E]xit and do nothing" + read OPTION + case $OPTION in + "D"|"d") + echo "drop database zm;"|mysql -u $MYADMIN $MYPASS + return + ;; + "E"|"e") + exit 0 + ;; + esac + done + + fi +} + +initdb(){ + sql=/tmp/zm.crdb.sql + echo "" >$sql + chmod 600 $sql + + echo "CREATE DATABASE $ZM_DB_NAME;" >>$sql + echo "USE $ZM_DB_NAME;" >>$sql + + echo "GRANT all on $ZM_DB_NAME.* TO '$ZM_DB_USER'@'$ClientHost' IDENTIFIED BY '$ZM_DB_PASS';" >>$sql + + cat $sql | mysql -B -h $ZM_DB_HOST -u $MYADMIN $MYPASS + rm -f $sql + + cat $ZM_PATH_UPDATE/zm_create.sql | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + +} + +restoredb(){ + if + [ -e $ZM_BACKUP ] + then + cat $ZM_BACKUP | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + else + echo "$ZM_BACKUP doesn't exist" + exit 1 + fi +} + +restore_events(){ + for SQL in $(find $ZM_PATH_WEB/$EVENTS_DIR -name .sql) + do + cat $SQL | mysql -h $ZM_DB_HOST -u $ZM_DB_USER -p$ZM_DB_PASS $ZM_DB_NAME + done +} + +loadcfg +chkcfg +reloadcfg +chk_backup_ver +getmylogin +checkfordb +initdb +restoredb +restore_events +exit 0 diff --git a/scripts/zmdc.pl b/scripts/zmdc.pl new file mode 100644 index 000000000..a63d0958b --- /dev/null +++ b/scripts/zmdc.pl @@ -0,0 +1,798 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Daemon Control Script, $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 script is the gateway for controlling the various ZoneMinder +# daemons. All starting, stopping and restarting goes through here. +# On the first invocation it starts up a server which subsequently +# records what's running and what's not. Other invocations just +# connect to the server and pass instructions to it. +# +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use POSIX; +use Socket; +use IO::Handle; +use Data::Dumper; + +use constant SOCK_FILE => ZM_PATH_SOCKS.'/zmdc.sock'; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my @daemons = ( + 'zmc', + 'zma', + 'zmf', + 'zmfilter.pl', + 'zmaudit.pl', + 'zmtrigger.pl', + 'zmx10.pl', + 'zmwatch.pl', + 'zmupdate.pl', + 'zmtrack.pl' +); + +sub Usage +{ + print( " +Usage: zmdc.pl [daemon [options]] +Parameters are :- + - One of 'startup|shutdown|status|check|logrot' or + 'start|stop|restart|reload'. +[daemon [options]] - Daemon name and options, required for second group of commands +"); + exit( -1 ); +} + +my $command = shift @ARGV; +if( !$command ) +{ + print( STDERR "No command given\n" ); + Usage(); +} +my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot)/; +my $daemon = shift( @ARGV ); +if( $needs_daemon && !$daemon ) +{ + print( STDERR "No daemon given\n" ); + Usage(); +} +my @args; + +my $daemon_patt = '('.join( '|', @daemons ).')'; +if ( $needs_daemon ) +{ + if ( $daemon =~ /^${daemon_patt}$/ ) + { + $daemon = $1; + } + else + { + print( STDERR "Invalid daemon '$daemon' specified" ); + Usage(); + } +} + +foreach my $arg ( @ARGV ) +{ + # Detaint arguments, if they look ok + #if ( $arg =~ /^(-{0,2}[\w]+)/ ) + if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) + { + push( @args, $1 ); + } + else + { + print( STDERR "Bogus argument '$arg' found" ); + exit( -1 ); + } +} + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( SOCK_FILE ); +my $server_up = connect( CLIENT, $saddr ); +if ( !$server_up ) +{ + if ( $command eq "logrot" ) + { + exit(); + } + if ( $command eq "check" ) + { + print( "stopped\n" ); + exit(); + } + elsif ( $command ne "startup" ) + { + print( "Unable to connect to server\n" ); + exit( -1 ); + } + # The server isn't there + print( "Starting server\n" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + logInit(); + + # Parent process just sleep and fall through + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + my $attempts = 0; + while (!connect( CLIENT, $saddr )) + { + $attempts++; + Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY); + sleep(1); + } + } + elsif ( defined($cpid) ) + { + ZMServer::run(); + } + else + { + Fatal( "Can't fork: $!" ); + } +} +if ( $command eq "check" && !$daemon ) +{ + print( "running\n" ); + exit(); +} +elsif ( $command eq "startup" ) +{ + # Our work here is done + exit() if ( !$server_up ); +} +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); +my $message = "$command"; +$message .= ";$daemon" if ( $daemon ); +$message .= ";".join( ';', @args ) if ( @args ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); +while ( my $line = ) +{ + chomp( $line ); + print( "$line\n" ); +} +# And we're done! +close( CLIENT ); +#print( "Finished writing, bye\n" ); + +exit; + +package ZMServer; + +use strict; +use bytes; + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use POSIX; +use Socket; +use IO::Handle; +use Data::Dumper; + +our %cmd_hash; +our %pid_hash; + +sub run +{ + my $fd = 0; + while( $fd < POSIX::sysconf( &POSIX::_SC_OPEN_MAX ) ) + { + POSIX::close( $fd++ ); + } + + setpgrp(); + + logInit(); + + dPrint( ZoneMinder::Logger::INFO, "Server starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + if ( open( PID, ">".ZM_PID ) ) + { + print( PID $$ ); + close( PID ); + } + + killAll( 1 ); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( main::SOCK_FILE ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + $SIG{CHLD} = \&reaper; + $SIG{INT} = \&shutdownAll; + $SIG{TERM} = \&shutdownAll; + $SIG{ABRT} = \&shutdownAll; + $SIG{HUP} = \&logrot; + + my $rin = ''; + vec( $rin, fileno(SERVER), 1 ) = 1; + my $win = $rin; + my $ein = $win; + my $timeout = 0.1; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER), 1 ) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + next if ( !$message ); + + my ( $command, $daemon, @args ) = split( /;/, $message ); + + if ( $command eq 'start' ) + { + start( $daemon, @args ); + } + elsif ( $command eq 'stop' ) + { + stop( $daemon, @args ); + } + elsif ( $command eq 'restart' ) + { + restart( $daemon, @args ); + } + elsif ( $command eq 'reload' ) + { + reload( $daemon, @args ); + } + elsif ( $command eq 'startup' ) + { + # Do nothing, this is all we're here for + dPrint( ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n" ); + } + elsif ( $command eq 'shutdown' ) + { + shutdownAll(); + } + elsif ( $command eq 'check' ) + { + check( $daemon, @args ); + } + elsif ( $command eq 'status' ) + { + if ( $daemon ) + { + status( $daemon, @args ); + } + else + { + status(); + } + } + elsif ( $command eq 'logrot' ) + { + logrot(); + } + else + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" ); + } + close( CLIENT ); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EINTR ) + { + # Dead child, will be reaped + #print( "Probable dead child\n" ); + # See if it needs to start up again + restartPending(); + } + elsif ( $! == EPIPE ) + { + Error( "Can't select: $!" ); + } + else + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + restartPending(); + } + } + dPrint( ZoneMinder::Logger::INFO, "Server exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + unlink( main::SOCK_FILE ); + unlink( ZM_PID ); + exit(); +} + +sub cPrint +{ + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } +} + +sub dPrint +{ + my $logLevel = shift; + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } + if ( $logLevel == ZoneMinder::Logger::DEBUG ) + { + Debug( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::INFO ) + { + Info( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::WARNING ) + { + Warning( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::ERROR ) + { + Error( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::FATAL ) + { + Fatal( @_ ); + } +} + +sub start +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + + if ( !$process ) + { + # It's not running, or at least it's not been started by us + $process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef }; + } + elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) + { + dPrint( ZoneMinder::Logger::INFO, "'$process->{command}' already running at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" ); + return(); + } + + my $sigset = POSIX::SigSet->new; + my $blockset = POSIX::SigSet->new( SIGCHLD ); + sigprocmask( SIG_BLOCK, $blockset, $sigset ) or Fatal( "Can't block SIGCHLD: $!" ); + if ( my $cpid = fork() ) + { + logReinit(); + + $process->{pid} = $cpid; + $process->{started} = time(); + delete( $process->{pending} ); + + dPrint( ZoneMinder::Logger::INFO, "'$command' starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" ); + + $cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process; + sigprocmask( SIG_SETMASK, $sigset ) or Fatal( "Can't restore SIGCHLD: $!" ); + } + elsif ( defined($cpid ) ) + { + logReinit(); + + dPrint( ZoneMinder::Logger::INFO, "'".join( ' ', ( $daemon, @args ) )."' started at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + if ( $daemon =~ /^${daemon_patt}$/ ) + { + $daemon = ZM_PATH_BIN.'/'.$1; + } + else + { + Fatal( "Invalid daemon '$daemon' specified" ); + } + + my @good_args; + foreach my $arg ( @args ) + { + # Detaint arguments, if they look ok + if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) + { + push( @good_args, $1 ); + } + else + { + Fatal( "Bogus argument '$arg' found" ); + } + } + + logTerm(); + + my $fd = 0; + while( $fd < POSIX::sysconf( &POSIX::_SC_OPEN_MAX ) ) + { + POSIX::close( $fd++ ); + } + + # Child process + $SIG{CHLD} = 'DEFAULT'; + $SIG{INT} = 'DEFAULT'; + $SIG{TERM} = 'DEFAULT'; + $SIG{ABRT} = 'DEFAULT'; + + exec( $daemon, @good_args ) or Fatal( "Can't exec: $!" ); + } + else + { + Fatal( "Can't fork: $!" ); + } +} + +sub _stop +{ + my $final = shift; + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + dPrint( ZoneMinder::Logger::WARNING, "Can't find process with command of '$command'\n" ); + return(); + } + elsif ( $process->{pending} ) + { + delete( $cmd_hash{$command} ); + dPrint( ZoneMinder::Logger::INFO, "Command '$command' removed from pending list at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + return(); + } + + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + dPrint( ZoneMinder::Logger::ERROR, "No process with command of '$command' is running\n" ); + return(); + } + + dPrint( ZoneMinder::Logger::INFO, "'$daemon ".join( ' ', @args )."' stopping at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + $process->{keepalive} = !$final; + kill( 'TERM', $cpid ); + delete( $cmd_hash{$command} ); + + # Now check it has actually gone away, if not kill -9 it + my $count = 0; + while( $cpid && kill( 0, $cpid ) ) + { + if ( $count++ > 5 ) + { + kill( 'KILL', $cpid ); + } + sleep( 1 ); + } +} + +sub stop +{ + _stop( 1, @_ ); +} + +sub restart +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( $process ) + { + if ( $process->{pid} ) + { + my $cpid = $process->{pid}; + if ( defined($pid_hash{$cpid}) ) + { + _stop( 0, $daemon, @args ); + return; + } + } + } + start( $daemon, @args ); +} + +sub reload +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( $process ) + { + if ( $process->{pid} ) + { + kill( 'HUP', $process->{pid} ); + } + } +} + +sub logrot +{ + logReinit(); + foreach my $process ( values( %pid_hash ) ) + { + if ( $process->{pid} && $process->{command} =~ /^zm.*\.pl/ ) + { + kill( 'HUP', $process->{pid} ); + } + } +} + +sub reaper +{ + my $saved_status = $!; + while ( (my $cpid = waitpid( -1, WNOHANG )) > 0 ) + { + my $status = $?; + + my $process = $pid_hash{$cpid}; + delete( $pid_hash{$cpid} ); + + if ( !$process ) + { + dPrint( ZoneMinder::Logger::INFO, "Can't find child with pid of '$cpid'\n" ); + next; + } + + $process->{stopped} = time(); + $process->{runtime} = ($process->{stopped}-$process->{started}); + delete( $process->{pid} ); + + my $exit_status = $status>>8; + my $exit_signal = $status&0xfe; + my $core_dumped = $status&0x01; + + my $out_str = "'$process->{daemon} ".join( ' ', @{$process->{args}} )."' "; + if ( $exit_signal ) + { + if ( $exit_signal == 15 || $exit_signal == 14 ) # TERM or ALRM + { + $out_str .= "exited"; + } + else + { + $out_str .= "crashed"; + } + $out_str .= ", signal $exit_signal"; + } + else + { + $out_str .= "exited "; + if ( $exit_status ) + { + $out_str .= "abnormally, exit status $exit_status"; + } + else + { + $out_str .= "normally"; + } + } + #print( ", core dumped" ) if ( $core_dumped ); + $out_str .= "\n"; + + if ( $exit_status == 0 ) + { + Info( $out_str ); + } + else + { + Error( $out_str ); + } + + if ( $process->{keepalive} ) + { + if ( !$process->{delay} || ($process->{runtime} > ZM_MAX_RESTART_DELAY) ) + { + #start( $process->{daemon}, @{$process->{args}} ); + # Schedule for immediate restart + $cmd_hash{$process->{command}} = $process; + $process->{pending} = $process->{stopped}; + $process->{delay} = 5; + } + else + { + $cmd_hash{$process->{command}} = $process; + $process->{pending} = $process->{stopped}+$process->{delay}; + $process->{delay} *= 2; + # Limit the start delay to 15 minutes max + if ( $process->{delay} > ZM_MAX_RESTART_DELAY ) + { + $process->{delay} = ZM_MAX_RESTART_DELAY; + } + } + } + } + $SIG{CHLD} = \&reaper; + $! = $saved_status; +} + +sub restartPending +{ + # Restart any pending processes + foreach my $process ( values( %cmd_hash ) ) + { + if ( $process->{pending} && $process->{pending} <= time() ) + { + dPrint( ZoneMinder::Logger::INFO, "Starting pending process, $process->{command}\n" ); + start( $process->{daemon}, @{$process->{args}} ); + } + } +} + +sub shutdownAll +{ + foreach my $process ( values( %pid_hash ) ) + { + stop( $process->{daemon}, @{$process->{args}} ); + } + killAll( 5 ); + dPrint( ZoneMinder::Logger::INFO, "Server shutdown at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + unlink( main::SOCK_FILE ); + unlink( ZM_PID ); + close( CLIENT ); + close( SERVER ); + exit(); +} + +sub check +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + cPrint( "unknown\n" ); + } + elsif ( $process->{pending} ) + { + cPrint( "pending\n" ); + } + else + { + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + cPrint( "stopped\n" ); + } + else + { + cPrint( "running\n" ); + } + } +} + +sub status +{ + my $daemon = shift; + my @args = @_; + + if ( defined($daemon) ) + { + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" ); + return(); + } + + if ( $process->{pending} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" ); + } + else + { + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" ); + return(); + } + } + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' running since ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}" ); + } + else + { + foreach my $process ( values(%pid_hash) ) + { + my $out_str = "'$process->{command}' running since ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}"; + $out_str .= ", valid" if ( kill( 0, $process->{pid} ) ); + $out_str .= "\n"; + dPrint( ZoneMinder::Logger::DEBUG, $out_str ); + } + foreach my $process ( values( %cmd_hash ) ) + { + if ( $process->{pending} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" ); + } + } + } +} + +sub killAll +{ + my $delay = shift; + sleep( $delay ); + foreach my $daemon ( @daemons ) + { + my $cmd = "killall --quiet --signal TERM $daemon"; + Debug( $cmd ); + qx( $cmd ); + } + sleep( $delay ); + foreach my $daemon ( @daemons ) + { + my $cmd = "killall --quiet --signal KILL $daemon"; + Debug( $cmd ); + qx( $cmd ); + } +} diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in new file mode 100644 index 000000000..47e50cc39 --- /dev/null +++ b/scripts/zmdc.pl.in @@ -0,0 +1,798 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Daemon Control Script, $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 script is the gateway for controlling the various ZoneMinder +# daemons. All starting, stopping and restarting goes through here. +# On the first invocation it starts up a server which subsequently +# records what's running and what's not. Other invocations just +# connect to the server and pass instructions to it. +# +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use POSIX; +use Socket; +use IO::Handle; +use Data::Dumper; + +use constant SOCK_FILE => ZM_PATH_SOCKS.'/zmdc.sock'; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my @daemons = ( + 'zmc', + 'zma', + 'zmf', + 'zmfilter.pl', + 'zmaudit.pl', + 'zmtrigger.pl', + 'zmx10.pl', + 'zmwatch.pl', + 'zmupdate.pl', + 'zmtrack.pl' +); + +sub Usage +{ + print( " +Usage: zmdc.pl [daemon [options]] +Parameters are :- + - One of 'startup|shutdown|status|check|logrot' or + 'start|stop|restart|reload'. +[daemon [options]] - Daemon name and options, required for second group of commands +"); + exit( -1 ); +} + +my $command = shift @ARGV; +if( !$command ) +{ + print( STDERR "No command given\n" ); + Usage(); +} +my $needs_daemon = $command !~ /(?:startup|shutdown|status|check|logrot)/; +my $daemon = shift( @ARGV ); +if( $needs_daemon && !$daemon ) +{ + print( STDERR "No daemon given\n" ); + Usage(); +} +my @args; + +my $daemon_patt = '('.join( '|', @daemons ).')'; +if ( $needs_daemon ) +{ + if ( $daemon =~ /^${daemon_patt}$/ ) + { + $daemon = $1; + } + else + { + print( STDERR "Invalid daemon '$daemon' specified" ); + Usage(); + } +} + +foreach my $arg ( @ARGV ) +{ + # Detaint arguments, if they look ok + #if ( $arg =~ /^(-{0,2}[\w]+)/ ) + if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) + { + push( @args, $1 ); + } + else + { + print( STDERR "Bogus argument '$arg' found" ); + exit( -1 ); + } +} + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( SOCK_FILE ); +my $server_up = connect( CLIENT, $saddr ); +if ( !$server_up ) +{ + if ( $command eq "logrot" ) + { + exit(); + } + if ( $command eq "check" ) + { + print( "stopped\n" ); + exit(); + } + elsif ( $command ne "startup" ) + { + print( "Unable to connect to server\n" ); + exit( -1 ); + } + # The server isn't there + print( "Starting server\n" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + logInit(); + + # Parent process just sleep and fall through + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + my $attempts = 0; + while (!connect( CLIENT, $saddr )) + { + $attempts++; + Fatal( "Can't connect: $!" ) if ($attempts > MAX_CONNECT_DELAY); + sleep(1); + } + } + elsif ( defined($cpid) ) + { + ZMServer::run(); + } + else + { + Fatal( "Can't fork: $!" ); + } +} +if ( $command eq "check" && !$daemon ) +{ + print( "running\n" ); + exit(); +} +elsif ( $command eq "startup" ) +{ + # Our work here is done + exit() if ( !$server_up ); +} +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); +my $message = "$command"; +$message .= ";$daemon" if ( $daemon ); +$message .= ";".join( ';', @args ) if ( @args ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); +while ( my $line = ) +{ + chomp( $line ); + print( "$line\n" ); +} +# And we're done! +close( CLIENT ); +#print( "Finished writing, bye\n" ); + +exit; + +package ZMServer; + +use strict; +use bytes; + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use POSIX; +use Socket; +use IO::Handle; +use Data::Dumper; + +our %cmd_hash; +our %pid_hash; + +sub run +{ + my $fd = 0; + while( $fd < POSIX::sysconf( &POSIX::_SC_OPEN_MAX ) ) + { + POSIX::close( $fd++ ); + } + + setpgrp(); + + logInit(); + + dPrint( ZoneMinder::Logger::INFO, "Server starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + if ( open( PID, ">".ZM_PID ) ) + { + print( PID $$ ); + close( PID ); + } + + killAll( 1 ); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( main::SOCK_FILE ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + $SIG{CHLD} = \&reaper; + $SIG{INT} = \&shutdownAll; + $SIG{TERM} = \&shutdownAll; + $SIG{ABRT} = \&shutdownAll; + $SIG{HUP} = \&logrot; + + my $rin = ''; + vec( $rin, fileno(SERVER), 1 ) = 1; + my $win = $rin; + my $ein = $win; + my $timeout = 0.1; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER), 1 ) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + next if ( !$message ); + + my ( $command, $daemon, @args ) = split( /;/, $message ); + + if ( $command eq 'start' ) + { + start( $daemon, @args ); + } + elsif ( $command eq 'stop' ) + { + stop( $daemon, @args ); + } + elsif ( $command eq 'restart' ) + { + restart( $daemon, @args ); + } + elsif ( $command eq 'reload' ) + { + reload( $daemon, @args ); + } + elsif ( $command eq 'startup' ) + { + # Do nothing, this is all we're here for + dPrint( ZoneMinder::Logger::WARNING, "Already running, ignoring command '$command'\n" ); + } + elsif ( $command eq 'shutdown' ) + { + shutdownAll(); + } + elsif ( $command eq 'check' ) + { + check( $daemon, @args ); + } + elsif ( $command eq 'status' ) + { + if ( $daemon ) + { + status( $daemon, @args ); + } + else + { + status(); + } + } + elsif ( $command eq 'logrot' ) + { + logrot(); + } + else + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" ); + } + close( CLIENT ); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EINTR ) + { + # Dead child, will be reaped + #print( "Probable dead child\n" ); + # See if it needs to start up again + restartPending(); + } + elsif ( $! == EPIPE ) + { + Error( "Can't select: $!" ); + } + else + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + restartPending(); + } + } + dPrint( ZoneMinder::Logger::INFO, "Server exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + unlink( main::SOCK_FILE ); + unlink( ZM_PID ); + exit(); +} + +sub cPrint +{ + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } +} + +sub dPrint +{ + my $logLevel = shift; + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } + if ( $logLevel == ZoneMinder::Logger::DEBUG ) + { + Debug( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::INFO ) + { + Info( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::WARNING ) + { + Warning( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::ERROR ) + { + Error( @_ ); + } + elsif ( $logLevel == ZoneMinder::Logger::FATAL ) + { + Fatal( @_ ); + } +} + +sub start +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + + if ( !$process ) + { + # It's not running, or at least it's not been started by us + $process = { daemon=>$daemon, args=>\@args, command=>$command, keepalive=>!undef }; + } + elsif ( $process->{pid} && $pid_hash{$process->{pid}} ) + { + dPrint( ZoneMinder::Logger::INFO, "'$process->{command}' already running at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" ); + return(); + } + + my $sigset = POSIX::SigSet->new; + my $blockset = POSIX::SigSet->new( SIGCHLD ); + sigprocmask( SIG_BLOCK, $blockset, $sigset ) or Fatal( "Can't block SIGCHLD: $!" ); + if ( my $cpid = fork() ) + { + logReinit(); + + $process->{pid} = $cpid; + $process->{started} = time(); + delete( $process->{pending} ); + + dPrint( ZoneMinder::Logger::INFO, "'$command' starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}\n" ); + + $cmd_hash{$process->{command}} = $pid_hash{$cpid} = $process; + sigprocmask( SIG_SETMASK, $sigset ) or Fatal( "Can't restore SIGCHLD: $!" ); + } + elsif ( defined($cpid ) ) + { + logReinit(); + + dPrint( ZoneMinder::Logger::INFO, "'".join( ' ', ( $daemon, @args ) )."' started at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + if ( $daemon =~ /^${daemon_patt}$/ ) + { + $daemon = ZM_PATH_BIN.'/'.$1; + } + else + { + Fatal( "Invalid daemon '$daemon' specified" ); + } + + my @good_args; + foreach my $arg ( @args ) + { + # Detaint arguments, if they look ok + if ( $arg =~ /^(-{0,2}[\w\/?&=.-]+)$/ ) + { + push( @good_args, $1 ); + } + else + { + Fatal( "Bogus argument '$arg' found" ); + } + } + + logTerm(); + + my $fd = 0; + while( $fd < POSIX::sysconf( &POSIX::_SC_OPEN_MAX ) ) + { + POSIX::close( $fd++ ); + } + + # Child process + $SIG{CHLD} = 'DEFAULT'; + $SIG{INT} = 'DEFAULT'; + $SIG{TERM} = 'DEFAULT'; + $SIG{ABRT} = 'DEFAULT'; + + exec( $daemon, @good_args ) or Fatal( "Can't exec: $!" ); + } + else + { + Fatal( "Can't fork: $!" ); + } +} + +sub _stop +{ + my $final = shift; + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + dPrint( ZoneMinder::Logger::WARNING, "Can't find process with command of '$command'\n" ); + return(); + } + elsif ( $process->{pending} ) + { + delete( $cmd_hash{$command} ); + dPrint( ZoneMinder::Logger::INFO, "Command '$command' removed from pending list at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + return(); + } + + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + dPrint( ZoneMinder::Logger::ERROR, "No process with command of '$command' is running\n" ); + return(); + } + + dPrint( ZoneMinder::Logger::INFO, "'$daemon ".join( ' ', @args )."' stopping at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + $process->{keepalive} = !$final; + kill( 'TERM', $cpid ); + delete( $cmd_hash{$command} ); + + # Now check it has actually gone away, if not kill -9 it + my $count = 0; + while( $cpid && kill( 0, $cpid ) ) + { + if ( $count++ > 5 ) + { + kill( 'KILL', $cpid ); + } + sleep( 1 ); + } +} + +sub stop +{ + _stop( 1, @_ ); +} + +sub restart +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( $process ) + { + if ( $process->{pid} ) + { + my $cpid = $process->{pid}; + if ( defined($pid_hash{$cpid}) ) + { + _stop( 0, $daemon, @args ); + return; + } + } + } + start( $daemon, @args ); +} + +sub reload +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( $process ) + { + if ( $process->{pid} ) + { + kill( 'HUP', $process->{pid} ); + } + } +} + +sub logrot +{ + logReinit(); + foreach my $process ( values( %pid_hash ) ) + { + if ( $process->{pid} && $process->{command} =~ /^zm.*\.pl/ ) + { + kill( 'HUP', $process->{pid} ); + } + } +} + +sub reaper +{ + my $saved_status = $!; + while ( (my $cpid = waitpid( -1, WNOHANG )) > 0 ) + { + my $status = $?; + + my $process = $pid_hash{$cpid}; + delete( $pid_hash{$cpid} ); + + if ( !$process ) + { + dPrint( ZoneMinder::Logger::INFO, "Can't find child with pid of '$cpid'\n" ); + next; + } + + $process->{stopped} = time(); + $process->{runtime} = ($process->{stopped}-$process->{started}); + delete( $process->{pid} ); + + my $exit_status = $status>>8; + my $exit_signal = $status&0xfe; + my $core_dumped = $status&0x01; + + my $out_str = "'$process->{daemon} ".join( ' ', @{$process->{args}} )."' "; + if ( $exit_signal ) + { + if ( $exit_signal == 15 || $exit_signal == 14 ) # TERM or ALRM + { + $out_str .= "exited"; + } + else + { + $out_str .= "crashed"; + } + $out_str .= ", signal $exit_signal"; + } + else + { + $out_str .= "exited "; + if ( $exit_status ) + { + $out_str .= "abnormally, exit status $exit_status"; + } + else + { + $out_str .= "normally"; + } + } + #print( ", core dumped" ) if ( $core_dumped ); + $out_str .= "\n"; + + if ( $exit_status == 0 ) + { + Info( $out_str ); + } + else + { + Error( $out_str ); + } + + if ( $process->{keepalive} ) + { + if ( !$process->{delay} || ($process->{runtime} > ZM_MAX_RESTART_DELAY) ) + { + #start( $process->{daemon}, @{$process->{args}} ); + # Schedule for immediate restart + $cmd_hash{$process->{command}} = $process; + $process->{pending} = $process->{stopped}; + $process->{delay} = 5; + } + else + { + $cmd_hash{$process->{command}} = $process; + $process->{pending} = $process->{stopped}+$process->{delay}; + $process->{delay} *= 2; + # Limit the start delay to 15 minutes max + if ( $process->{delay} > ZM_MAX_RESTART_DELAY ) + { + $process->{delay} = ZM_MAX_RESTART_DELAY; + } + } + } + } + $SIG{CHLD} = \&reaper; + $! = $saved_status; +} + +sub restartPending +{ + # Restart any pending processes + foreach my $process ( values( %cmd_hash ) ) + { + if ( $process->{pending} && $process->{pending} <= time() ) + { + dPrint( ZoneMinder::Logger::INFO, "Starting pending process, $process->{command}\n" ); + start( $process->{daemon}, @{$process->{args}} ); + } + } +} + +sub shutdownAll +{ + foreach my $process ( values( %pid_hash ) ) + { + stop( $process->{daemon}, @{$process->{args}} ); + } + killAll( 5 ); + dPrint( ZoneMinder::Logger::INFO, "Server shutdown at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + unlink( main::SOCK_FILE ); + unlink( ZM_PID ); + close( CLIENT ); + close( SERVER ); + exit(); +} + +sub check +{ + my $daemon = shift; + my @args = @_; + + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + cPrint( "unknown\n" ); + } + elsif ( $process->{pending} ) + { + cPrint( "pending\n" ); + } + else + { + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + cPrint( "stopped\n" ); + } + else + { + cPrint( "running\n" ); + } + } +} + +sub status +{ + my $daemon = shift; + my @args = @_; + + if ( defined($daemon) ) + { + my $command = $daemon; + $command .= ' '.join( ' ', ( @args ) ) if ( @args ); + my $process = $cmd_hash{$command}; + if ( !$process ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" ); + return(); + } + + if ( $process->{pending} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" ); + } + else + { + my $cpid = $process->{pid}; + if ( !$pid_hash{$cpid} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$command' not running\n" ); + return(); + } + } + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' running since ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}" ); + } + else + { + foreach my $process ( values(%pid_hash) ) + { + my $out_str = "'$process->{command}' running since ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{started}) ).", pid = $process->{pid}"; + $out_str .= ", valid" if ( kill( 0, $process->{pid} ) ); + $out_str .= "\n"; + dPrint( ZoneMinder::Logger::DEBUG, $out_str ); + } + foreach my $process ( values( %cmd_hash ) ) + { + if ( $process->{pending} ) + { + dPrint( ZoneMinder::Logger::DEBUG, "'$process->{command}' pending at ".strftime( '%y/%m/%d %H:%M:%S', localtime( $process->{pending}) )."\n" ); + } + } + } +} + +sub killAll +{ + my $delay = shift; + sleep( $delay ); + foreach my $daemon ( @daemons ) + { + my $cmd = "killall --quiet --signal TERM $daemon"; + Debug( $cmd ); + qx( $cmd ); + } + sleep( $delay ); + foreach my $daemon ( @daemons ) + { + my $cmd = "killall --quiet --signal KILL $daemon"; + Debug( $cmd ); + qx( $cmd ); + } +} diff --git a/scripts/zmeventdump b/scripts/zmeventdump new file mode 100644 index 000000000..074b38ed4 --- /dev/null +++ b/scripts/zmeventdump @@ -0,0 +1,50 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmeventdump +# +# USAGE: ./zmeventdump +# +# DESCRIPTION: Uses mysqldump to create a .sql file for individual zm +# events to make Event table recovery possible by doing a +# 'find' search in ZoneMinder the events directory +# +# OPTIONS: --- None +# REQUIREMENTS: --- mysqldump +# BUGS: --- +# NOTES: --- +# AUTHOR: Ross Melin +# COMPANY: +# VERSION: 3.0 +# CREATED: 02/27/2008 05:39:00 PM PST +# REVISION: --- Update for changed zmfilter and +# ZM_USE_DEEP_STORAGE +#=============================================================================== + +# Edit these to suit your configuration +ZM_CONFIG=/etc/zm/zm.conf +MYSQLDUMP=/usr/bin/mysqldump + +# The rest should not need editing + +# Get the mysql user and password +source $ZM_CONFIG + +# zmfilter now passes the full path as an argument +EVENT_PATH=$1 + +# Get the event id from a filename in the event directory +EVENT_ID=$(ls $1/.[0-9]* | sed s:$1\/\.::) + +MYDUMPOPTS="--user=$ZM_DB_USER --password=$ZM_DB_PASS --skip-opt --compact --quick --no-create-info" + +# Dump the sql statements needed to reload the Events, Frames and Stats tables + +echo "-- ZM_DB_VERSION=$ZM_VERSION + " > $EVENT_PATH/.sql + +$MYSQLDUMP $MYDUMPOPTS --where="Id=$EVENT_ID" zm Events >> $EVENT_PATH/.sql +$MYSQLDUMP $MYDUMPOPTS --where="Eventid=$EVENT_ID" zm Frames >> $EVENT_PATH/.sql +$MYSQLDUMP $MYDUMPOPTS --where="Eventid=$EVENT_ID" zm Stats >> $EVENT_PATH/.sql + +exit 0 diff --git a/scripts/zmeventdump.in b/scripts/zmeventdump.in new file mode 100644 index 000000000..342b665b0 --- /dev/null +++ b/scripts/zmeventdump.in @@ -0,0 +1,50 @@ +#!/bin/bash +#=============================================================================== +# +# FILE: zmeventdump +# +# USAGE: ./zmeventdump +# +# DESCRIPTION: Uses mysqldump to create a .sql file for individual zm +# events to make Event table recovery possible by doing a +# 'find' search in ZoneMinder the events directory +# +# OPTIONS: --- None +# REQUIREMENTS: --- mysqldump +# BUGS: --- +# NOTES: --- +# AUTHOR: Ross Melin +# COMPANY: +# VERSION: 3.0 +# CREATED: 02/27/2008 05:39:00 PM PST +# REVISION: --- Update for changed zmfilter and +# ZM_USE_DEEP_STORAGE +#=============================================================================== + +# Edit these to suit your configuration +ZM_CONFIG=@ZM_CONFIG@ +MYSQLDUMP=/usr/bin/mysqldump + +# The rest should not need editing + +# Get the mysql user and password +source $ZM_CONFIG + +# zmfilter now passes the full path as an argument +EVENT_PATH=$1 + +# Get the event id from a filename in the event directory +EVENT_ID=$(ls $1/.[0-9]* | sed s:$1\/\.::) + +MYDUMPOPTS="--user=$ZM_DB_USER --password=$ZM_DB_PASS --skip-opt --compact --quick --no-create-info" + +# Dump the sql statements needed to reload the Events, Frames and Stats tables + +echo "-- ZM_DB_VERSION=$ZM_VERSION + " > $EVENT_PATH/.sql + +$MYSQLDUMP $MYDUMPOPTS --where="Id=$EVENT_ID" zm Events >> $EVENT_PATH/.sql +$MYSQLDUMP $MYDUMPOPTS --where="Eventid=$EVENT_ID" zm Frames >> $EVENT_PATH/.sql +$MYSQLDUMP $MYDUMPOPTS --where="Eventid=$EVENT_ID" zm Stats >> $EVENT_PATH/.sql + +exit 0 diff --git a/scripts/zmfilter.pl b/scripts/zmfilter.pl new file mode 100644 index 000000000..f3d906685 --- /dev/null +++ b/scripts/zmfilter.pl @@ -0,0 +1,1169 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Event Filter Script, $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 script continuously monitors the recorded events for the given +# monitor and applies any filters which would delete and/or upload +# matching events +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant START_DELAY => 5; # How long to wait before starting + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use DBI; +use POSIX; +use Time::HiRes qw/gettimeofday/; +use Date::Manip; +use Getopt::Long; +use Data::Dumper; + +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +logInit(); +logSetSignal(); + +if ( ZM_OPT_UPLOAD ) +{ + # Comment these out if you don't have them and don't want to upload + # or don't want to use that format + if ( ZM_UPLOAD_ARCH_FORMAT eq "zip" ) + { + require Archive::Zip; + import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + } + else + { + require Archive::Tar; + } + if ( ZM_UPLOAD_PROTOCOL eq "ftp" ) + { + require Net::FTP; + } + else + { + require Net::SFTP::Foreign; + } +} + +if ( ZM_OPT_EMAIL ) +{ + if ( ZM_NEW_MAIL_MODULES ) + { + require MIME::Lite; + require Net::SMTP; + } + else + { + require MIME::Entity; + } +} + +if ( ZM_OPT_MESSAGE ) +{ + if ( ZM_NEW_MAIL_MODULES ) + { + require MIME::Lite; + require Net::SMTP; + } + else + { + require MIME::Entity; + } +} + + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $delay = ZM_FILTER_EXECUTE_INTERVAL; +my $event_id = 0; +my $filter_parm = ""; + +sub Usage +{ + print( " +Usage: zmfilter.pl [-f ,--filter=] +Parameters are :- +-f, --filter= - The name of a specific filter to run +"); + exit( -1 ); +} + +# +# More or less replicates the equivalent PHP function +# +sub strtotime +{ + my $dt_str = shift; + return( UnixDate( $dt_str, '%s' ) ); +} + +# +# More or less replicates the equivalent PHP function +# +sub str_repeat +{ + my $string = shift; + my $count = shift; + return( ${string}x${count} ); +} + +# Formats a date into MySQL format +sub DateTimeToSQL +{ + my $dt_str = shift; + my $dt_val = strtotime( $dt_str ); + if ( !$dt_val ) + { + Error( "Unable to parse date string '$dt_str'\n" ); + return( undef ); + } + return( strftime( "%Y-%m-%d %H:%M:%S", localtime( $dt_val ) ) ); +} + +if ( !GetOptions( 'filter=s'=>\$filter_parm ) ) +{ + Usage(); +} + +chdir( EVENT_PATH ); + +my $dbh = zmDbConnect(); + +if ( $filter_parm ) +{ + Info( "Scanning for events using filter '$filter_parm'\n" ); +} +else +{ + Info( "Scanning for events\n" ); +} + +if ( !$filter_parm ) +{ + sleep( START_DELAY ); +} + +my $filters; +my $last_action = 0; + +while( 1 ) +{ + if ( (time() - $last_action) > ZM_FILTER_RELOAD_DELAY ) + { + Debug( "Reloading filters\n" ); + $last_action = time(); + $filters = getFilters( $filter_parm ); + } + + foreach my $filter ( @$filters ) + { + checkFilter( $filter ); + } + + last if ( $filter_parm ); + + Debug( "Sleeping for $delay seconds\n" ); + sleep( $delay ); +} + +sub getDiskPercent +{ + my $command = "df ."; + my $df = qx( $command ); + my $space = -1; + if ( $df =~ /\s(\d+)%/ms ) + { + $space = $1; + } + return( $space ); +} + +sub getDiskBlocks +{ + my $command = "df ."; + my $df = qx( $command ); + my $space = -1; + if ( $df =~ /\s(\d+)\s+\d+\s+\d+%/ms ) + { + $space = $1; + } + return( $space ); +} + +sub getLoad +{ + my $command = "uptime ."; + my $uptime = qx( $command ); + my $load = -1; + if ( $uptime =~ /load average:\s+([\d.]+)/ms ) + { + $load = $1; + Info( "Load: $load" ); + } + return( $load ); +} + +sub getFilters +{ + my $filter_name = shift; + + my @filters; + my $sql = "select * from Filters where"; + if ( $filter_name ) + { + $sql .= " Name = ? and"; + } + else + { + $sql .= " Background = 1 and"; + } + $sql .= " (AutoArchive = 1 or AutoVideo = 1 or AutoUpload = 1 or AutoEmail = 1 or AutoMessage = 1 or AutoExecute = 1 or AutoDelete = 1) order by Name"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res; + if ( $filter_name ) + { + $res = $sth->execute( $filter_name ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + else + { + $res = $sth->execute() or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) + { + Debug( "Found filter '$db_filter->{Name}'\n" ); + my $filter_expr = jsonDecode( $db_filter->{Query} ); + my $sql = "select E.Id,E.MonitorId,M.Name as MonitorName,M.DefaultRate,M.DefaultScale,E.Name,E.Cause,E.Notes,E.StartTime,unix_timestamp(E.StartTime) as Time,E.Length,E.Frames,E.AlarmFrames,E.TotScore,E.AvgScore,E.MaxScore,E.Archived,E.Videoed,E.Uploaded,E.Emailed,E.Messaged,E.Executed from Events as E inner join Monitors as M on M.Id = E.MonitorId where not isnull(E.EndTime)"; + $db_filter->{Sql} = ''; + + if ( @{$filter_expr->{terms}} ) + { + for ( my $i = 0; $i < @{$filter_expr->{terms}}; $i++ ) + { + if ( exists($filter_expr->{terms}[$i]->{cnj}) ) + { + $db_filter->{Sql} .= " ".$filter_expr->{terms}[$i]->{cnj}." "; + } + if ( exists($filter_expr->{terms}[$i]->{obr}) ) + { + $db_filter->{Sql} .= " ".str_repeat( "(", $filter_expr->{terms}[$i]->{obr} )." "; + } + my $value = $filter_expr->{terms}[$i]->{val}; + my @value_list; + if ( $filter_expr->{terms}[$i]->{attr} ) + { + if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) + { + my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/; + $db_filter->{Sql} .= "M.".$temp_attr_name; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) + { + $db_filter->{Sql} .= "E.StartTime"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) + { + $db_filter->{Sql} .= "to_days( E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) + { + $db_filter->{Sql} .= "extract( hour_second from E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Weekday' ) + { + $db_filter->{Sql} .= "weekday( E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskPercent' ) + { + $db_filter->{Sql} .= "zmDiskPercent"; + $db_filter->{HasDiskPercent} = !undef; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskBlocks' ) + { + $db_filter->{Sql} .= "zmDiskBlocks"; + $db_filter->{HasDiskBlocks} = !undef; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'SystemLoad' ) + { + $db_filter->{Sql} .= "zmSystemLoad"; + $db_filter->{HasSystemLoad} = !undef; + } + else + { + $db_filter->{Sql} .= "E.".$filter_expr->{terms}[$i]->{attr}; + } + + ( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/; + foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) + { + if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) + { + $value = "'$temp_value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name' || $filter_expr->{terms}[$i]->{attr} eq 'Cause' || $filter_expr->{terms}[$i]->{attr} eq 'Notes' ) + { + $value = "'$temp_value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "'$value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "to_days( '$value' )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "extract( hour_second from '$value' )"; + } + else + { + $value = $temp_value; + } + push( @value_list, $value ); + } + } + if ( $filter_expr->{terms}[$i]->{op} ) + { + if ( $filter_expr->{terms}[$i]->{op} eq '=~' ) + { + $db_filter->{Sql} .= " regexp $value"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) + { + $db_filter->{Sql} .= " not regexp $value"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '=[]' ) + { + $db_filter->{Sql} .= " in (".join( ",", @value_list ).")"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) + { + $db_filter->{Sql} .= " not in (".join( ",", @value_list ).")"; + } + else + { + $db_filter->{Sql} .= " ".$filter_expr->{terms}[$i]->{op}." $value"; + } + } + if ( exists($filter_expr->{terms}[$i]->{cbr}) ) + { + $db_filter->{Sql} .= " ".str_repeat( ")", $filter_expr->{terms}[$i]->{cbr} )." "; + } + } + } + if ( $db_filter->{Sql} ) + { + $sql .= " and ( ".$db_filter->{Sql}." )"; + } + my @auto_terms; + if ( $db_filter->{AutoArchive} ) + { + push( @auto_terms, "E.Archived = 0" ) + } + if ( $db_filter->{AutoVideo} ) + { + push( @auto_terms, "E.Videoed = 0" ) + } + if ( $db_filter->{AutoUpload} ) + { + push( @auto_terms, "E.Uploaded = 0" ) + } + if ( $db_filter->{AutoEmail} ) + { + push( @auto_terms, "E.Emailed = 0" ) + } + if ( $db_filter->{AutoMessage} ) + { + push( @auto_terms, "E.Messaged = 0" ) + } + if ( $db_filter->{AutoExecute} ) + { + push( @auto_terms, "E.Executed = 0" ) + } + if ( @auto_terms ) + { + $sql .= " and ( ".join( " or ", @auto_terms )." )"; + } + if ( !$filter_expr->{sort_field} ) + { + $filter_expr->{sort_field} = 'StartTime'; + $filter_expr->{sort_asc} = 0; + } + my $sort_column = ''; + if ( $filter_expr->{sort_field} eq 'Id' ) + { + $sort_column = "E.Id"; + } + elsif ( $filter_expr->{sort_field} eq 'MonitorName' ) + { + $sort_column = "M.Name"; + } + elsif ( $filter_expr->{sort_field} eq 'Name' ) + { + $sort_column = "E.Name"; + } + elsif ( $filter_expr->{sort_field} eq 'StartTime' ) + { + $sort_column = "E.StartTime"; + } + elsif ( $filter_expr->{sort_field} eq 'Secs' ) + { + $sort_column = "E.Length"; + } + elsif ( $filter_expr->{sort_field} eq 'Frames' ) + { + $sort_column = "E.Frames"; + } + elsif ( $filter_expr->{sort_field} eq 'AlarmFrames' ) + { + $sort_column = "E.AlarmFrames"; + } + elsif ( $filter_expr->{sort_field} eq 'TotScore' ) + { + $sort_column = "E.TotScore"; + } + elsif ( $filter_expr->{sort_field} eq 'AvgScore' ) + { + $sort_column = "E.AvgScore"; + } + elsif ( $filter_expr->{sort_field} eq 'MaxScore' ) + { + $sort_column = "E.MaxScore"; + } + else + { + $sort_column = "E.StartTime"; + } + my $sort_order = $filter_expr->{sort_asc}?"asc":"desc"; + $sql .= " order by ".$sort_column." ".$sort_order; + if ( $filter_expr->{limit} ) + { + $sql .= " limit 0,".$filter_expr->{limit}; + } + Debug( "SQL:$sql\n" ); + $db_filter->{Sql} = $sql; + if ( $db_filter->{AutoExecute} ) + { + my $script = $db_filter->{AutoExecuteCmd}; + $script =~ s/\s.*$//; + if ( !-e $script ) + { + Error( "Auto execute script '$script' not found, skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + + } + elsif ( !-x $script ) + { + Error( "Auto execute script '$script' not executable, skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + } + push( @filters, $db_filter ); + } + $sth->finish(); + + return( \@filters ); +} + +sub checkFilter +{ + my $filter = shift; + + Debug( "Checking filter '$filter->{Name}'". + ($filter->{AutoDelete}?", delete":""). + ($filter->{AutoArchive}?", archive":""). + ($filter->{AutoVideo}?", video":""). + ($filter->{AutoUpload}?", upload":""). + ($filter->{AutoEmail}?", email":""). + ($filter->{AutoMessage}?", message":""). + ($filter->{AutoExecute}?", execute":""). + "\n" + ); + my $sql = $filter->{Sql}; + + if ( $filter->{HasDiskPercent} ) + { + my $disk_percent = getDiskPercent(); + $sql =~ s/zmDiskPercent/$disk_percent/g; + } + if ( $filter->{HasDiskBlocks} ) + { + my $disk_blocks = getDiskBlocks(); + $sql =~ s/zmDiskBlocks/$disk_blocks/g; + } + if ( $filter->{HasSystemLoad} ) + { + my $load = getLoad(); + $sql =~ s/zmSystemLoad/$load/g; + } + + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute(); + if ( !$res ) + { + Error( "Can't execute filter '$sql', ignoring: ".$sth->errstr() ); + return; + } + + while( my $event = $sth->fetchrow_hashref() ) + { + Debug( "Checking event $event->{Id}\n" ); + my $delete_ok = !undef; + if ( $filter->{AutoArchive} ) + { + Info( "Archiving event $event->{Id}\n" ); + # Do it individually to avoid locking up the table for new events + my $sql = "update Events set Archived = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + if ( ZM_OPT_FFMPEG && $filter->{AutoVideo} ) + { + if ( !$event->{Videoed} ) + { + $delete_ok = undef if ( !generateVideo( $filter, $event ) ); + } + } + if ( ZM_OPT_EMAIL && $filter->{AutoEmail} ) + { + if ( !$event->{Emailed} ) + { + $delete_ok = undef if ( !sendEmail( $filter, $event ) ); + } + } + if ( ZM_OPT_MESSAGE && $filter->{AutoMessage} ) + { + if ( !$event->{Messaged} ) + { + $delete_ok = undef if ( !sendMessage( $filter, $event ) ); + } + } + if ( ZM_OPT_UPLOAD && $filter->{AutoUpload} ) + { + if ( !$event->{Uploaded} ) + { + $delete_ok = undef if ( !uploadArchFile( $filter, $event ) ); + } + } + if ( $filter->{AutoExecute} ) + { + if ( !$event->{Execute} ) + { + $delete_ok = undef if ( !executeCommand( $filter, $event ) ); + } + } + if ( $filter->{AutoDelete} ) + { + if ( $delete_ok ) + { + Info( "Deleting event $event->{Id}\n" ); + # Do it individually to avoid locking up the table for new events + my $sql = "delete from Events where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + if ( !ZM_OPT_FAST_DELETE ) + { + my $sql = "delete from Frames where EventId = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + $sql = "delete from Stats where EventId = ?"; + $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + deleteEventFiles( $event->{Id}, $event->{MonitorId} ); + } + } + else + { + Error( "Unable to delete event $event->{Id} as previous operations failed\n" ); + } + } + } + $sth->finish(); +} + +sub generateVideo +{ + my $filter = shift; + my $event = shift; + my $phone = shift; + + my $rate = $event->{DefaultRate}/100; + my $scale = $event->{DefaultScale}/100; + my $format; + + my @ffmpeg_formats = split( /\s+/, ZM_FFMPEG_FORMATS ); + my $default_video_format; + my $default_phone_format; + foreach my $ffmpeg_format( @ffmpeg_formats ) + { + if ( $ffmpeg_format =~ /^(.+)\*\*$/ ) + { + $default_phone_format = $1; + } + elsif ( $ffmpeg_format =~ /^(.+)\*$/ ) + { + $default_video_format = $1; + } + } + + if ( $phone && $default_phone_format ) + { + $format = $default_phone_format; + } + elsif ( $default_video_format ) + { + $format = $default_video_format; + } + else + { + $format = $ffmpeg_formats[0]; + } + + my $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event->{Id}." -r ".$rate." -s ".$scale." -f ".$format; + my $output = qx($command); + chomp( $output ); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Video generation '$command' failed with status: $status\n" ); + if ( wantarray() ) + { + return( undef, undef ); + } + return( 0 ); + } + else + { + my $sql = "update Events set Videoed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + if ( wantarray() ) + { + return( $format, sprintf( "%s/%s", getEventPath( $event ), $output ) ); + } + } + return( 1 ); +} + +sub uploadArchFile +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_UPLOAD_HOST ) + { + Error( "Cannot upload archive as no upload host defined" ); + return( 0 ); + } + + my $archFile = $event->{MonitorName}.'-'.$event->{Id}; + my $archImagePath = getEventPath( $event )."/".((ZM_UPLOAD_ARCH_ANALYSE)?'{*analyse,*capture}':'*capture').".jpg"; + my @archImageFiles = glob($archImagePath); + my $archLocPath; + + my $archError = 0; + if ( ZM_UPLOAD_ARCH_FORMAT eq "zip" ) + { + $archFile .= '.zip'; + $archLocPath = ZM_UPLOAD_LOC_DIR.'/'.$archFile; + my $zip = Archive::Zip->new(); + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + + my $status = &AZ_OK; + foreach my $imageFile ( @archImageFiles ) + { + Debug( "Adding $imageFile\n" ); + my $member = $zip->addFile( $imageFile ); + if ( !$member ) + { + Error( "Unable to add image file $imageFile to zip archive $archLocPath" ); + $archError = 1; + last; + } + $member->desiredCompressionMethod( (ZM_UPLOAD_ARCH_COMPRESS)?&COMPRESSION_DEFLATED:&COMPRESSION_STORED ); + } + if ( !$archError ) + { + $status = $zip->writeToFileNamed( $archLocPath ); + + if ( $archError = ($status != &AZ_OK) ) + { + Error( "Zip error: $status\n " ); + } + } + else + { + Error( "Error adding images to zip archive $archLocPath, not writing" ); + } + } + elsif ( ZM_UPLOAD_ARCH_FORMAT eq "tar" ) + { + if ( ZM_UPLOAD_ARCH_COMPRESS ) + { + $archFile .= '.tar.gz'; + } + else + { + $archFile .= '.tar'; + } + $archLocPath = ZM_UPLOAD_LOC_DIR.'/'.$archFile; + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + + if ( $archError = !Archive::Tar->create_archive( $archLocPath, ZM_UPLOAD_ARCH_COMPRESS, @archImageFiles ) ) + { + Error( "Tar error: ".Archive::Tar->error()."\n " ); + } + } + + if ( $archError ) + { + return( 0 ); + } + else + { + if ( ZM_UPLOAD_PROTOCOL eq "ftp" ) + { + Info( "Uploading to ".ZM_UPLOAD_HOST." using FTP\n" ); + my $ftp = Net::FTP->new( ZM_UPLOAD_HOST, Timeout=>ZM_UPLOAD_TIMEOUT, Passive=>ZM_UPLOAD_FTP_PASSIVE, Debug=>ZM_UPLOAD_DEBUG ); + if ( !$ftp ) + { + Error( "Can't create FTP connection: $@" ); + return( 0 ); + } + $ftp->login( ZM_UPLOAD_USER, ZM_UPLOAD_PASS ) or Error( "FTP - Can't login" ); + $ftp->binary() or Error( "FTP - Can't go binary" ); + $ftp->cwd( ZM_UPLOAD_REM_DIR ) or Error( "FTP - Can't cwd" ) if ( ZM_UPLOAD_REM_DIR ); + $ftp->put( $archLocPath ) or Error( "FTP - Can't upload '$archLocPath'" ); + $ftp->quit() or Error( "FTP - Can't quit" ); + } + else + { + my $host = ZM_UPLOAD_HOST; + $host .= ":".ZM_UPLOAD_PORT if ( ZM_UPLOAD_PORT ); + Info( "Uploading to ".$host." using SFTP\n" ); + my %sftpOptions = ( host=>ZM_UPLOAD_HOST, user=>ZM_UPLOAD_USER ); + $sftpOptions{password} = ZM_UPLOAD_PASS if ( ZM_UPLOAD_PASS ); + $sftpOptions{port} = ZM_UPLOAD_PORT if ( ZM_UPLOAD_PORT ); + $sftpOptions{timeout} = ZM_UPLOAD_TIMEOUT if ( ZM_UPLOAD_TIMEOUT ); + $sftpOptions{more} = [ '-o'=>'StrictHostKeyChecking=no' ]; + $Net::SFTP::Foreign::debug = -1 if ( ZM_UPLOAD_DEBUG ); + my $sftp = Net::SFTP::Foreign->new( ZM_UPLOAD_HOST, %sftpOptions ); + if ( $sftp->error ) + { + Error( "Can't create SFTP connection: ".$sftp->error ); + return( 0 ); + } + $sftp->setcwd( ZM_UPLOAD_REM_DIR ) or Error( "SFTP - Can't setcwd: ".$sftp->error ) if ( ZM_UPLOAD_REM_DIR ); + $sftp->put( $archLocPath, $archFile ) or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error ); + } + unlink( $archLocPath ); + my $sql = "update Events set Uploaded = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); +} + +sub substituteTags +{ + my $text = shift; + my $filter = shift; + my $event = shift; + my $attachments_ref = shift; + + # First we'd better check what we need to get + # We have a filter and an event, do we need any more + # monitor information? + my $need_monitor = $text =~ /%(?:MET|MEH|MED|MEW|MEN|MEA)%/; + + my $monitor = {}; + if ( $need_monitor ) + { + my $db_now = strftime( "%Y-%m-%d %H:%M:%S", localtime() ); + my $sql = "select M.Id, count(E.Id) as EventCount, count(if(E.Archived,1,NULL)) as ArchEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) as HourEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) as DayEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) as WeekEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) as MonthEventCount from Monitors as M left join Events as E on E.MonitorId = M.Id where MonitorId = ? group by E.MonitorId order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{MonitorId} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + $monitor = $sth->fetchrow_hashref(); + $sth->finish(); + return() if ( !$monitor ); + } + + # Do we need the image information too? + my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM)%/; + my $first_alarm_frame; + my $max_alarm_frame; + my $max_alarm_score = 0; + if ( $need_images ) + { + my $sql = "select * from Frames where EventId = ? and Type = 'Alarm' order by FrameId"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + while( my $frame = $sth->fetchrow_hashref() ) + { + if ( !$first_alarm_frame ) + { + $first_alarm_frame = $frame; + } + if ( $frame->{Score} > $max_alarm_score ) + { + $max_alarm_frame = $frame; + $max_alarm_score = $frame->{Score}; + } + } + $sth->finish(); + } + + my $url = ZM_URL; + $text =~ s/%ZP%/$url/g; + $text =~ s/%MN%/$event->{MonitorName}/g; + $text =~ s/%MET%/$monitor->{EventCount}/g; + $text =~ s/%MEH%/$monitor->{HourEventCount}/g; + $text =~ s/%MED%/$monitor->{DayEventCount}/g; + $text =~ s/%MEW%/$monitor->{WeekEventCount}/g; + $text =~ s/%MEM%/$monitor->{MonthEventCount}/g; + $text =~ s/%MEA%/$monitor->{ArchEventCount}/g; + $text =~ s/%MP%/$url?view=watch&mid=$event->{MonitorId}/g; + $text =~ s/%MPS%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=stream/g; + $text =~ s/%MPI%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=still/g; + $text =~ s/%EP%/$url?view=event&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPS%/$url?view=event&mode=stream&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPI%/$url?view=event&mode=still&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EI%/$event->{Id}/g; + $text =~ s/%EN%/$event->{Name}/g; + $text =~ s/%EC%/$event->{Cause}/g; + $text =~ s/%ED%/$event->{Notes}/g; + $text =~ s/%ET%/$event->{StartTime}/g; + $text =~ s/%EL%/$event->{Length}/g; + $text =~ s/%EF%/$event->{Frames}/g; + $text =~ s/%EFA%/$event->{AlarmFrames}/g; + $text =~ s/%EST%/$event->{TotScore}/g; + $text =~ s/%ESA%/$event->{AvgScore}/g; + $text =~ s/%ESM%/$event->{MaxScore}/g; + if ( $first_alarm_frame ) + { + $text =~ s/%EPI1%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g; + $text =~ s/%EPIM%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g; + if ( $attachments_ref && $text =~ s/%EI1%//g ) + { + push( @$attachments_ref, { type=>"image/jpeg", path=>sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", getEventPath( $event ), $first_alarm_frame->{FrameId} ) } ); + } + if ( $attachments_ref && $text =~ s/%EIM%//g ) + { + # Don't attach the same image twice + if ( !@$attachments_ref || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) ) + { + push( @$attachments_ref, { type=>"image/jpeg", path=>sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", getEventPath( $event ), $max_alarm_frame->{FrameId} ) } ); + } + } + } + if ( $attachments_ref && ZM_OPT_FFMPEG ) + { + if ( $text =~ s/%EV%//g ) + { + my ( $format, $path ) = generateVideo( $filter, $event ); + if ( !$format ) + { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + if ( $text =~ s/%EVM%//g ) + { + my ( $format, $path ) = generateVideo( $filter, $event, 1 ); + if ( !$format ) + { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + } + $text =~ s/%FN%/$filter->{Name}/g; + ( my $filter_name = $filter->{Name} ) =~ s/ /+/g; + $text =~ s/%FP%/$url?view=filter&mid=$event->{MonitorId}&filter_name=$filter_name/g; + + return( $text ); +} + +sub sendEmail +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_FROM_EMAIL ) + { + Error( "No 'from' email address defined, not sending email" ); + return( 0 ); + } + if ( !ZM_EMAIL_ADDRESS ) + { + Error( "No email address defined, not sending email" ); + return( 0 ); + } + + Info( "Creating notification email\n" ); + + my $subject = substituteTags( ZM_EMAIL_SUBJECT, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( ZM_EMAIL_BODY, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification email '$subject'\n" ); + + eval + { + if ( ZM_NEW_MAIL_MODULES ) + { + ### Create the multipart container + my $mail = MIME::Lite->new ( + From => ZM_FROM_EMAIL, + To => ZM_EMAIL_ADDRESS, + Subject => $subject, + Type => "multipart/mixed" + ); + ### Add the text message part + $mail->attach ( + Type => "TEXT", + Data => $body + ); + ### Add the attachments + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => "attachment" + ); + } + ### Send the Message + MIME::Lite->send( "smtp", ZM_EMAIL_HOST, Timeout=>60 ); + $mail->send(); + } + else + { + my $mail = MIME::Entity->build( + From => ZM_FROM_EMAIL, + To => ZM_EMAIL_ADDRESS, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => "base64" + ); + } + $mail->smtpsend( Host => ZM_EMAIL_HOST, MailFrom => ZM_FROM_EMAIL ); + } + }; + if ( $@ ) + { + Error( "Can't send email: $@" ); + return( 0 ); + } + else + { + Info( "Notification email sent\n" ); + } + my $sql = "update Events set Emailed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); +} + +sub sendMessage +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_FROM_EMAIL ) + { + Error( "No 'from' email address defined, not sending message" ); + return( 0 ); + } + if ( !ZM_MESSAGE_ADDRESS ) + { + Error( "No message address defined, not sending message" ); + return( 0 ); + } + + Info( "Creating notification message\n" ); + + my $subject = substituteTags( ZM_MESSAGE_SUBJECT, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( ZM_MESSAGE_BODY, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification message '$subject'\n" ); + + eval + { + if ( ZM_NEW_MAIL_MODULES ) + { + ### Create the multipart container + my $mail = MIME::Lite->new ( + From => ZM_FROM_EMAIL, + To => ZM_MESSAGE_ADDRESS, + Subject => $subject, + Type => "multipart/mixed" + ); + ### Add the text message part + $mail->attach ( + Type => "TEXT", + Data => $body + ); + ### Add the attachments + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => "attachment" + ); + } + ### Send the Message + MIME::Lite->send( "smtp", ZM_EMAIL_HOST, Timeout=>60 ); + $mail->send(); + } + else + { + my $mail = MIME::Entity->build( + From => ZM_FROM_EMAIL, + To => ZM_MESSAGE_ADDRESS, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => "base64" + ); + } + $mail->smtpsend( Host => ZM_EMAIL_HOST, MailFrom => ZM_FROM_EMAIL ); + } + }; + if ( $@ ) + { + Error( "Can't send email: $@" ); + return( 0 ); + } + else + { + Info( "Notification message sent\n" ); + } + my $sql = "update Events set Messaged = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); +} + +sub executeCommand +{ + my $filter = shift; + my $event = shift; + + my $event_path = getEventPath( $event ); + + my $command = $filter->{AutoExecuteCmd}; + $command .= " $event_path"; + + Info( "Executing '$command'\n" ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Command '$command' exited with status: $status\n" ); + return( 0 ); + } + else + { + my $sql = "update Events set Executed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); +} + diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in new file mode 100644 index 000000000..19e7a8977 --- /dev/null +++ b/scripts/zmfilter.pl.in @@ -0,0 +1,1169 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Event Filter Script, $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 script continuously monitors the recorded events for the given +# monitor and applies any filters which would delete and/or upload +# matching events +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant START_DELAY => 5; # How long to wait before starting + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use DBI; +use POSIX; +use Time::HiRes qw/gettimeofday/; +use Date::Manip; +use Getopt::Long; +use Data::Dumper; + +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +logInit(); +logSetSignal(); + +if ( ZM_OPT_UPLOAD ) +{ + # Comment these out if you don't have them and don't want to upload + # or don't want to use that format + if ( ZM_UPLOAD_ARCH_FORMAT eq "zip" ) + { + require Archive::Zip; + import Archive::Zip qw( :ERROR_CODES :CONSTANTS ); + } + else + { + require Archive::Tar; + } + if ( ZM_UPLOAD_PROTOCOL eq "ftp" ) + { + require Net::FTP; + } + else + { + require Net::SFTP::Foreign; + } +} + +if ( ZM_OPT_EMAIL ) +{ + if ( ZM_NEW_MAIL_MODULES ) + { + require MIME::Lite; + require Net::SMTP; + } + else + { + require MIME::Entity; + } +} + +if ( ZM_OPT_MESSAGE ) +{ + if ( ZM_NEW_MAIL_MODULES ) + { + require MIME::Lite; + require Net::SMTP; + } + else + { + require MIME::Entity; + } +} + + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $delay = ZM_FILTER_EXECUTE_INTERVAL; +my $event_id = 0; +my $filter_parm = ""; + +sub Usage +{ + print( " +Usage: zmfilter.pl [-f ,--filter=] +Parameters are :- +-f, --filter= - The name of a specific filter to run +"); + exit( -1 ); +} + +# +# More or less replicates the equivalent PHP function +# +sub strtotime +{ + my $dt_str = shift; + return( UnixDate( $dt_str, '%s' ) ); +} + +# +# More or less replicates the equivalent PHP function +# +sub str_repeat +{ + my $string = shift; + my $count = shift; + return( ${string}x${count} ); +} + +# Formats a date into MySQL format +sub DateTimeToSQL +{ + my $dt_str = shift; + my $dt_val = strtotime( $dt_str ); + if ( !$dt_val ) + { + Error( "Unable to parse date string '$dt_str'\n" ); + return( undef ); + } + return( strftime( "%Y-%m-%d %H:%M:%S", localtime( $dt_val ) ) ); +} + +if ( !GetOptions( 'filter=s'=>\$filter_parm ) ) +{ + Usage(); +} + +chdir( EVENT_PATH ); + +my $dbh = zmDbConnect(); + +if ( $filter_parm ) +{ + Info( "Scanning for events using filter '$filter_parm'\n" ); +} +else +{ + Info( "Scanning for events\n" ); +} + +if ( !$filter_parm ) +{ + sleep( START_DELAY ); +} + +my $filters; +my $last_action = 0; + +while( 1 ) +{ + if ( (time() - $last_action) > ZM_FILTER_RELOAD_DELAY ) + { + Debug( "Reloading filters\n" ); + $last_action = time(); + $filters = getFilters( $filter_parm ); + } + + foreach my $filter ( @$filters ) + { + checkFilter( $filter ); + } + + last if ( $filter_parm ); + + Debug( "Sleeping for $delay seconds\n" ); + sleep( $delay ); +} + +sub getDiskPercent +{ + my $command = "df ."; + my $df = qx( $command ); + my $space = -1; + if ( $df =~ /\s(\d+)%/ms ) + { + $space = $1; + } + return( $space ); +} + +sub getDiskBlocks +{ + my $command = "df ."; + my $df = qx( $command ); + my $space = -1; + if ( $df =~ /\s(\d+)\s+\d+\s+\d+%/ms ) + { + $space = $1; + } + return( $space ); +} + +sub getLoad +{ + my $command = "uptime ."; + my $uptime = qx( $command ); + my $load = -1; + if ( $uptime =~ /load average:\s+([\d.]+)/ms ) + { + $load = $1; + Info( "Load: $load" ); + } + return( $load ); +} + +sub getFilters +{ + my $filter_name = shift; + + my @filters; + my $sql = "select * from Filters where"; + if ( $filter_name ) + { + $sql .= " Name = ? and"; + } + else + { + $sql .= " Background = 1 and"; + } + $sql .= " (AutoArchive = 1 or AutoVideo = 1 or AutoUpload = 1 or AutoEmail = 1 or AutoMessage = 1 or AutoExecute = 1 or AutoDelete = 1) order by Name"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res; + if ( $filter_name ) + { + $res = $sth->execute( $filter_name ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + else + { + $res = $sth->execute() or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + FILTER: while( my $db_filter = $sth->fetchrow_hashref() ) + { + Debug( "Found filter '$db_filter->{Name}'\n" ); + my $filter_expr = jsonDecode( $db_filter->{Query} ); + my $sql = "select E.Id,E.MonitorId,M.Name as MonitorName,M.DefaultRate,M.DefaultScale,E.Name,E.Cause,E.Notes,E.StartTime,unix_timestamp(E.StartTime) as Time,E.Length,E.Frames,E.AlarmFrames,E.TotScore,E.AvgScore,E.MaxScore,E.Archived,E.Videoed,E.Uploaded,E.Emailed,E.Messaged,E.Executed from Events as E inner join Monitors as M on M.Id = E.MonitorId where not isnull(E.EndTime)"; + $db_filter->{Sql} = ''; + + if ( @{$filter_expr->{terms}} ) + { + for ( my $i = 0; $i < @{$filter_expr->{terms}}; $i++ ) + { + if ( exists($filter_expr->{terms}[$i]->{cnj}) ) + { + $db_filter->{Sql} .= " ".$filter_expr->{terms}[$i]->{cnj}." "; + } + if ( exists($filter_expr->{terms}[$i]->{obr}) ) + { + $db_filter->{Sql} .= " ".str_repeat( "(", $filter_expr->{terms}[$i]->{obr} )." "; + } + my $value = $filter_expr->{terms}[$i]->{val}; + my @value_list; + if ( $filter_expr->{terms}[$i]->{attr} ) + { + if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) + { + my ( $temp_attr_name ) = $filter_expr->{terms}[$i]->{attr} =~ /^Monitor(.+)$/; + $db_filter->{Sql} .= "M.".$temp_attr_name; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) + { + $db_filter->{Sql} .= "E.StartTime"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) + { + $db_filter->{Sql} .= "to_days( E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) + { + $db_filter->{Sql} .= "extract( hour_second from E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Weekday' ) + { + $db_filter->{Sql} .= "weekday( E.StartTime )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskPercent' ) + { + $db_filter->{Sql} .= "zmDiskPercent"; + $db_filter->{HasDiskPercent} = !undef; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DiskBlocks' ) + { + $db_filter->{Sql} .= "zmDiskBlocks"; + $db_filter->{HasDiskBlocks} = !undef; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'SystemLoad' ) + { + $db_filter->{Sql} .= "zmSystemLoad"; + $db_filter->{HasSystemLoad} = !undef; + } + else + { + $db_filter->{Sql} .= "E.".$filter_expr->{terms}[$i]->{attr}; + } + + ( my $stripped_value = $value ) =~ s/^["\']+?(.+)["\']+?$/$1/; + foreach my $temp_value ( split( /["'\s]*?,["'\s]*?/, $stripped_value ) ) + { + if ( $filter_expr->{terms}[$i]->{attr} =~ /^Monitor/ ) + { + $value = "'$temp_value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Name' || $filter_expr->{terms}[$i]->{attr} eq 'Cause' || $filter_expr->{terms}[$i]->{attr} eq 'Notes' ) + { + $value = "'$temp_value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'DateTime' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "'$value'"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Date' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "to_days( '$value' )"; + } + elsif ( $filter_expr->{terms}[$i]->{attr} eq 'Time' ) + { + $value = DateTimeToSQL( $temp_value ); + if ( !$value ) + { + Error( "Error parsing date/time '$temp_value', skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + $value = "extract( hour_second from '$value' )"; + } + else + { + $value = $temp_value; + } + push( @value_list, $value ); + } + } + if ( $filter_expr->{terms}[$i]->{op} ) + { + if ( $filter_expr->{terms}[$i]->{op} eq '=~' ) + { + $db_filter->{Sql} .= " regexp $value"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) + { + $db_filter->{Sql} .= " not regexp $value"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '=[]' ) + { + $db_filter->{Sql} .= " in (".join( ",", @value_list ).")"; + } + elsif ( $filter_expr->{terms}[$i]->{op} eq '!~' ) + { + $db_filter->{Sql} .= " not in (".join( ",", @value_list ).")"; + } + else + { + $db_filter->{Sql} .= " ".$filter_expr->{terms}[$i]->{op}." $value"; + } + } + if ( exists($filter_expr->{terms}[$i]->{cbr}) ) + { + $db_filter->{Sql} .= " ".str_repeat( ")", $filter_expr->{terms}[$i]->{cbr} )." "; + } + } + } + if ( $db_filter->{Sql} ) + { + $sql .= " and ( ".$db_filter->{Sql}." )"; + } + my @auto_terms; + if ( $db_filter->{AutoArchive} ) + { + push( @auto_terms, "E.Archived = 0" ) + } + if ( $db_filter->{AutoVideo} ) + { + push( @auto_terms, "E.Videoed = 0" ) + } + if ( $db_filter->{AutoUpload} ) + { + push( @auto_terms, "E.Uploaded = 0" ) + } + if ( $db_filter->{AutoEmail} ) + { + push( @auto_terms, "E.Emailed = 0" ) + } + if ( $db_filter->{AutoMessage} ) + { + push( @auto_terms, "E.Messaged = 0" ) + } + if ( $db_filter->{AutoExecute} ) + { + push( @auto_terms, "E.Executed = 0" ) + } + if ( @auto_terms ) + { + $sql .= " and ( ".join( " or ", @auto_terms )." )"; + } + if ( !$filter_expr->{sort_field} ) + { + $filter_expr->{sort_field} = 'StartTime'; + $filter_expr->{sort_asc} = 0; + } + my $sort_column = ''; + if ( $filter_expr->{sort_field} eq 'Id' ) + { + $sort_column = "E.Id"; + } + elsif ( $filter_expr->{sort_field} eq 'MonitorName' ) + { + $sort_column = "M.Name"; + } + elsif ( $filter_expr->{sort_field} eq 'Name' ) + { + $sort_column = "E.Name"; + } + elsif ( $filter_expr->{sort_field} eq 'StartTime' ) + { + $sort_column = "E.StartTime"; + } + elsif ( $filter_expr->{sort_field} eq 'Secs' ) + { + $sort_column = "E.Length"; + } + elsif ( $filter_expr->{sort_field} eq 'Frames' ) + { + $sort_column = "E.Frames"; + } + elsif ( $filter_expr->{sort_field} eq 'AlarmFrames' ) + { + $sort_column = "E.AlarmFrames"; + } + elsif ( $filter_expr->{sort_field} eq 'TotScore' ) + { + $sort_column = "E.TotScore"; + } + elsif ( $filter_expr->{sort_field} eq 'AvgScore' ) + { + $sort_column = "E.AvgScore"; + } + elsif ( $filter_expr->{sort_field} eq 'MaxScore' ) + { + $sort_column = "E.MaxScore"; + } + else + { + $sort_column = "E.StartTime"; + } + my $sort_order = $filter_expr->{sort_asc}?"asc":"desc"; + $sql .= " order by ".$sort_column." ".$sort_order; + if ( $filter_expr->{limit} ) + { + $sql .= " limit 0,".$filter_expr->{limit}; + } + Debug( "SQL:$sql\n" ); + $db_filter->{Sql} = $sql; + if ( $db_filter->{AutoExecute} ) + { + my $script = $db_filter->{AutoExecuteCmd}; + $script =~ s/\s.*$//; + if ( !-e $script ) + { + Error( "Auto execute script '$script' not found, skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + + } + elsif ( !-x $script ) + { + Error( "Auto execute script '$script' not executable, skipping filter '$db_filter->{Name}'\n" ); + next FILTER; + } + } + push( @filters, $db_filter ); + } + $sth->finish(); + + return( \@filters ); +} + +sub checkFilter +{ + my $filter = shift; + + Debug( "Checking filter '$filter->{Name}'". + ($filter->{AutoDelete}?", delete":""). + ($filter->{AutoArchive}?", archive":""). + ($filter->{AutoVideo}?", video":""). + ($filter->{AutoUpload}?", upload":""). + ($filter->{AutoEmail}?", email":""). + ($filter->{AutoMessage}?", message":""). + ($filter->{AutoExecute}?", execute":""). + "\n" + ); + my $sql = $filter->{Sql}; + + if ( $filter->{HasDiskPercent} ) + { + my $disk_percent = getDiskPercent(); + $sql =~ s/zmDiskPercent/$disk_percent/g; + } + if ( $filter->{HasDiskBlocks} ) + { + my $disk_blocks = getDiskBlocks(); + $sql =~ s/zmDiskBlocks/$disk_blocks/g; + } + if ( $filter->{HasSystemLoad} ) + { + my $load = getLoad(); + $sql =~ s/zmSystemLoad/$load/g; + } + + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute(); + if ( !$res ) + { + Error( "Can't execute filter '$sql', ignoring: ".$sth->errstr() ); + return; + } + + while( my $event = $sth->fetchrow_hashref() ) + { + Debug( "Checking event $event->{Id}\n" ); + my $delete_ok = !undef; + if ( $filter->{AutoArchive} ) + { + Info( "Archiving event $event->{Id}\n" ); + # Do it individually to avoid locking up the table for new events + my $sql = "update Events set Archived = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + if ( ZM_OPT_FFMPEG && $filter->{AutoVideo} ) + { + if ( !$event->{Videoed} ) + { + $delete_ok = undef if ( !generateVideo( $filter, $event ) ); + } + } + if ( ZM_OPT_EMAIL && $filter->{AutoEmail} ) + { + if ( !$event->{Emailed} ) + { + $delete_ok = undef if ( !sendEmail( $filter, $event ) ); + } + } + if ( ZM_OPT_MESSAGE && $filter->{AutoMessage} ) + { + if ( !$event->{Messaged} ) + { + $delete_ok = undef if ( !sendMessage( $filter, $event ) ); + } + } + if ( ZM_OPT_UPLOAD && $filter->{AutoUpload} ) + { + if ( !$event->{Uploaded} ) + { + $delete_ok = undef if ( !uploadArchFile( $filter, $event ) ); + } + } + if ( $filter->{AutoExecute} ) + { + if ( !$event->{Execute} ) + { + $delete_ok = undef if ( !executeCommand( $filter, $event ) ); + } + } + if ( $filter->{AutoDelete} ) + { + if ( $delete_ok ) + { + Info( "Deleting event $event->{Id}\n" ); + # Do it individually to avoid locking up the table for new events + my $sql = "delete from Events where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + if ( !ZM_OPT_FAST_DELETE ) + { + my $sql = "delete from Frames where EventId = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + $sql = "delete from Stats where EventId = ?"; + $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + deleteEventFiles( $event->{Id}, $event->{MonitorId} ); + } + } + else + { + Error( "Unable to delete event $event->{Id} as previous operations failed\n" ); + } + } + } + $sth->finish(); +} + +sub generateVideo +{ + my $filter = shift; + my $event = shift; + my $phone = shift; + + my $rate = $event->{DefaultRate}/100; + my $scale = $event->{DefaultScale}/100; + my $format; + + my @ffmpeg_formats = split( /\s+/, ZM_FFMPEG_FORMATS ); + my $default_video_format; + my $default_phone_format; + foreach my $ffmpeg_format( @ffmpeg_formats ) + { + if ( $ffmpeg_format =~ /^(.+)\*\*$/ ) + { + $default_phone_format = $1; + } + elsif ( $ffmpeg_format =~ /^(.+)\*$/ ) + { + $default_video_format = $1; + } + } + + if ( $phone && $default_phone_format ) + { + $format = $default_phone_format; + } + elsif ( $default_video_format ) + { + $format = $default_video_format; + } + else + { + $format = $ffmpeg_formats[0]; + } + + my $command = ZM_PATH_BIN."/zmvideo.pl -e ".$event->{Id}." -r ".$rate." -s ".$scale." -f ".$format; + my $output = qx($command); + chomp( $output ); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Video generation '$command' failed with status: $status\n" ); + if ( wantarray() ) + { + return( undef, undef ); + } + return( 0 ); + } + else + { + my $sql = "update Events set Videoed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + if ( wantarray() ) + { + return( $format, sprintf( "%s/%s", getEventPath( $event ), $output ) ); + } + } + return( 1 ); +} + +sub uploadArchFile +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_UPLOAD_HOST ) + { + Error( "Cannot upload archive as no upload host defined" ); + return( 0 ); + } + + my $archFile = $event->{MonitorName}.'-'.$event->{Id}; + my $archImagePath = getEventPath( $event )."/".((ZM_UPLOAD_ARCH_ANALYSE)?'{*analyse,*capture}':'*capture').".jpg"; + my @archImageFiles = glob($archImagePath); + my $archLocPath; + + my $archError = 0; + if ( ZM_UPLOAD_ARCH_FORMAT eq "zip" ) + { + $archFile .= '.zip'; + $archLocPath = ZM_UPLOAD_LOC_DIR.'/'.$archFile; + my $zip = Archive::Zip->new(); + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + + my $status = &AZ_OK; + foreach my $imageFile ( @archImageFiles ) + { + Debug( "Adding $imageFile\n" ); + my $member = $zip->addFile( $imageFile ); + if ( !$member ) + { + Error( "Unable to add image file $imageFile to zip archive $archLocPath" ); + $archError = 1; + last; + } + $member->desiredCompressionMethod( (ZM_UPLOAD_ARCH_COMPRESS)?&COMPRESSION_DEFLATED:&COMPRESSION_STORED ); + } + if ( !$archError ) + { + $status = $zip->writeToFileNamed( $archLocPath ); + + if ( $archError = ($status != &AZ_OK) ) + { + Error( "Zip error: $status\n " ); + } + } + else + { + Error( "Error adding images to zip archive $archLocPath, not writing" ); + } + } + elsif ( ZM_UPLOAD_ARCH_FORMAT eq "tar" ) + { + if ( ZM_UPLOAD_ARCH_COMPRESS ) + { + $archFile .= '.tar.gz'; + } + else + { + $archFile .= '.tar'; + } + $archLocPath = ZM_UPLOAD_LOC_DIR.'/'.$archFile; + Info( "Creating upload file '$archLocPath', ".int(@archImageFiles)." files\n" ); + + if ( $archError = !Archive::Tar->create_archive( $archLocPath, ZM_UPLOAD_ARCH_COMPRESS, @archImageFiles ) ) + { + Error( "Tar error: ".Archive::Tar->error()."\n " ); + } + } + + if ( $archError ) + { + return( 0 ); + } + else + { + if ( ZM_UPLOAD_PROTOCOL eq "ftp" ) + { + Info( "Uploading to ".ZM_UPLOAD_HOST." using FTP\n" ); + my $ftp = Net::FTP->new( ZM_UPLOAD_HOST, Timeout=>ZM_UPLOAD_TIMEOUT, Passive=>ZM_UPLOAD_FTP_PASSIVE, Debug=>ZM_UPLOAD_DEBUG ); + if ( !$ftp ) + { + Error( "Can't create FTP connection: $@" ); + return( 0 ); + } + $ftp->login( ZM_UPLOAD_USER, ZM_UPLOAD_PASS ) or Error( "FTP - Can't login" ); + $ftp->binary() or Error( "FTP - Can't go binary" ); + $ftp->cwd( ZM_UPLOAD_REM_DIR ) or Error( "FTP - Can't cwd" ) if ( ZM_UPLOAD_REM_DIR ); + $ftp->put( $archLocPath ) or Error( "FTP - Can't upload '$archLocPath'" ); + $ftp->quit() or Error( "FTP - Can't quit" ); + } + else + { + my $host = ZM_UPLOAD_HOST; + $host .= ":".ZM_UPLOAD_PORT if ( ZM_UPLOAD_PORT ); + Info( "Uploading to ".$host." using SFTP\n" ); + my %sftpOptions = ( host=>ZM_UPLOAD_HOST, user=>ZM_UPLOAD_USER ); + $sftpOptions{password} = ZM_UPLOAD_PASS if ( ZM_UPLOAD_PASS ); + $sftpOptions{port} = ZM_UPLOAD_PORT if ( ZM_UPLOAD_PORT ); + $sftpOptions{timeout} = ZM_UPLOAD_TIMEOUT if ( ZM_UPLOAD_TIMEOUT ); + $sftpOptions{more} = [ '-o'=>'StrictHostKeyChecking=no' ]; + $Net::SFTP::Foreign::debug = -1 if ( ZM_UPLOAD_DEBUG ); + my $sftp = Net::SFTP::Foreign->new( ZM_UPLOAD_HOST, %sftpOptions ); + if ( $sftp->error ) + { + Error( "Can't create SFTP connection: ".$sftp->error ); + return( 0 ); + } + $sftp->setcwd( ZM_UPLOAD_REM_DIR ) or Error( "SFTP - Can't setcwd: ".$sftp->error ) if ( ZM_UPLOAD_REM_DIR ); + $sftp->put( $archLocPath, $archFile ) or Error( "SFTP - Can't upload '$archLocPath': ".$sftp->error ); + } + unlink( $archLocPath ); + my $sql = "update Events set Uploaded = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); +} + +sub substituteTags +{ + my $text = shift; + my $filter = shift; + my $event = shift; + my $attachments_ref = shift; + + # First we'd better check what we need to get + # We have a filter and an event, do we need any more + # monitor information? + my $need_monitor = $text =~ /%(?:MET|MEH|MED|MEW|MEN|MEA)%/; + + my $monitor = {}; + if ( $need_monitor ) + { + my $db_now = strftime( "%Y-%m-%d %H:%M:%S", localtime() ); + my $sql = "select M.Id, count(E.Id) as EventCount, count(if(E.Archived,1,NULL)) as ArchEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 HOUR && E.Archived = 0,1,NULL)) as HourEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 DAY && E.Archived = 0,1,NULL)) as DayEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 7 DAY && E.Archived = 0,1,NULL)) as WeekEventCount, count(if(E.StartTime>'$db_now' - INTERVAL 1 MONTH && E.Archived = 0,1,NULL)) as MonthEventCount from Monitors as M left join Events as E on E.MonitorId = M.Id where MonitorId = ? group by E.MonitorId order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{MonitorId} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + $monitor = $sth->fetchrow_hashref(); + $sth->finish(); + return() if ( !$monitor ); + } + + # Do we need the image information too? + my $need_images = $text =~ /%(?:EPI1|EPIM|EI1|EIM)%/; + my $first_alarm_frame; + my $max_alarm_frame; + my $max_alarm_score = 0; + if ( $need_images ) + { + my $sql = "select * from Frames where EventId = ? and Type = 'Alarm' order by FrameId"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + while( my $frame = $sth->fetchrow_hashref() ) + { + if ( !$first_alarm_frame ) + { + $first_alarm_frame = $frame; + } + if ( $frame->{Score} > $max_alarm_score ) + { + $max_alarm_frame = $frame; + $max_alarm_score = $frame->{Score}; + } + } + $sth->finish(); + } + + my $url = ZM_URL; + $text =~ s/%ZP%/$url/g; + $text =~ s/%MN%/$event->{MonitorName}/g; + $text =~ s/%MET%/$monitor->{EventCount}/g; + $text =~ s/%MEH%/$monitor->{HourEventCount}/g; + $text =~ s/%MED%/$monitor->{DayEventCount}/g; + $text =~ s/%MEW%/$monitor->{WeekEventCount}/g; + $text =~ s/%MEM%/$monitor->{MonthEventCount}/g; + $text =~ s/%MEA%/$monitor->{ArchEventCount}/g; + $text =~ s/%MP%/$url?view=watch&mid=$event->{MonitorId}/g; + $text =~ s/%MPS%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=stream/g; + $text =~ s/%MPI%/$url?view=watchfeed&mid=$event->{MonitorId}&mode=still/g; + $text =~ s/%EP%/$url?view=event&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPS%/$url?view=event&mode=stream&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EPI%/$url?view=event&mode=still&mid=$event->{MonitorId}&eid=$event->{Id}/g; + $text =~ s/%EI%/$event->{Id}/g; + $text =~ s/%EN%/$event->{Name}/g; + $text =~ s/%EC%/$event->{Cause}/g; + $text =~ s/%ED%/$event->{Notes}/g; + $text =~ s/%ET%/$event->{StartTime}/g; + $text =~ s/%EL%/$event->{Length}/g; + $text =~ s/%EF%/$event->{Frames}/g; + $text =~ s/%EFA%/$event->{AlarmFrames}/g; + $text =~ s/%EST%/$event->{TotScore}/g; + $text =~ s/%ESA%/$event->{AvgScore}/g; + $text =~ s/%ESM%/$event->{MaxScore}/g; + if ( $first_alarm_frame ) + { + $text =~ s/%EPI1%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$first_alarm_frame->{FrameId}/g; + $text =~ s/%EPIM%/$url?view=frame&mid=$event->{MonitorId}&eid=$event->{Id}&fid=$max_alarm_frame->{FrameId}/g; + if ( $attachments_ref && $text =~ s/%EI1%//g ) + { + push( @$attachments_ref, { type=>"image/jpeg", path=>sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", getEventPath( $event ), $first_alarm_frame->{FrameId} ) } ); + } + if ( $attachments_ref && $text =~ s/%EIM%//g ) + { + # Don't attach the same image twice + if ( !@$attachments_ref || ($first_alarm_frame->{FrameId} != $max_alarm_frame->{FrameId} ) ) + { + push( @$attachments_ref, { type=>"image/jpeg", path=>sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg", getEventPath( $event ), $max_alarm_frame->{FrameId} ) } ); + } + } + } + if ( $attachments_ref && ZM_OPT_FFMPEG ) + { + if ( $text =~ s/%EV%//g ) + { + my ( $format, $path ) = generateVideo( $filter, $event ); + if ( !$format ) + { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + if ( $text =~ s/%EVM%//g ) + { + my ( $format, $path ) = generateVideo( $filter, $event, 1 ); + if ( !$format ) + { + return( undef ); + } + push( @$attachments_ref, { type=>"video/$format", path=>$path } ); + } + } + $text =~ s/%FN%/$filter->{Name}/g; + ( my $filter_name = $filter->{Name} ) =~ s/ /+/g; + $text =~ s/%FP%/$url?view=filter&mid=$event->{MonitorId}&filter_name=$filter_name/g; + + return( $text ); +} + +sub sendEmail +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_FROM_EMAIL ) + { + Error( "No 'from' email address defined, not sending email" ); + return( 0 ); + } + if ( !ZM_EMAIL_ADDRESS ) + { + Error( "No email address defined, not sending email" ); + return( 0 ); + } + + Info( "Creating notification email\n" ); + + my $subject = substituteTags( ZM_EMAIL_SUBJECT, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( ZM_EMAIL_BODY, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification email '$subject'\n" ); + + eval + { + if ( ZM_NEW_MAIL_MODULES ) + { + ### Create the multipart container + my $mail = MIME::Lite->new ( + From => ZM_FROM_EMAIL, + To => ZM_EMAIL_ADDRESS, + Subject => $subject, + Type => "multipart/mixed" + ); + ### Add the text message part + $mail->attach ( + Type => "TEXT", + Data => $body + ); + ### Add the attachments + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => "attachment" + ); + } + ### Send the Message + MIME::Lite->send( "smtp", ZM_EMAIL_HOST, Timeout=>60 ); + $mail->send(); + } + else + { + my $mail = MIME::Entity->build( + From => ZM_FROM_EMAIL, + To => ZM_EMAIL_ADDRESS, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => "base64" + ); + } + $mail->smtpsend( Host => ZM_EMAIL_HOST, MailFrom => ZM_FROM_EMAIL ); + } + }; + if ( $@ ) + { + Error( "Can't send email: $@" ); + return( 0 ); + } + else + { + Info( "Notification email sent\n" ); + } + my $sql = "update Events set Emailed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); +} + +sub sendMessage +{ + my $filter = shift; + my $event = shift; + + if ( !ZM_FROM_EMAIL ) + { + Error( "No 'from' email address defined, not sending message" ); + return( 0 ); + } + if ( !ZM_MESSAGE_ADDRESS ) + { + Error( "No message address defined, not sending message" ); + return( 0 ); + } + + Info( "Creating notification message\n" ); + + my $subject = substituteTags( ZM_MESSAGE_SUBJECT, $filter, $event ); + return( 0 ) if ( !$subject ); + my @attachments; + my $body = substituteTags( ZM_MESSAGE_BODY, $filter, $event, \@attachments ); + return( 0 ) if ( !$body ); + + Info( "Sending notification message '$subject'\n" ); + + eval + { + if ( ZM_NEW_MAIL_MODULES ) + { + ### Create the multipart container + my $mail = MIME::Lite->new ( + From => ZM_FROM_EMAIL, + To => ZM_MESSAGE_ADDRESS, + Subject => $subject, + Type => "multipart/mixed" + ); + ### Add the text message part + $mail->attach ( + Type => "TEXT", + Data => $body + ); + ### Add the attachments + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Disposition => "attachment" + ); + } + ### Send the Message + MIME::Lite->send( "smtp", ZM_EMAIL_HOST, Timeout=>60 ); + $mail->send(); + } + else + { + my $mail = MIME::Entity->build( + From => ZM_FROM_EMAIL, + To => ZM_MESSAGE_ADDRESS, + Subject => $subject, + Type => (($body=~//)?'text/html':'text/plain'), + Data => $body + ); + + foreach my $attachment ( @attachments ) + { + Info( "Attaching '$attachment->{path}\n" ); + $mail->attach( + Path => $attachment->{path}, + Type => $attachment->{type}, + Encoding => "base64" + ); + } + $mail->smtpsend( Host => ZM_EMAIL_HOST, MailFrom => ZM_FROM_EMAIL ); + } + }; + if ( $@ ) + { + Error( "Can't send email: $@" ); + return( 0 ); + } + else + { + Info( "Notification message sent\n" ); + } + my $sql = "update Events set Messaged = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + + return( 1 ); +} + +sub executeCommand +{ + my $filter = shift; + my $event = shift; + + my $event_path = getEventPath( $event ); + + my $command = $filter->{AutoExecuteCmd}; + $command .= " $event_path"; + + Info( "Executing '$command'\n" ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + Debug( "Output: $output\n" ); + } + if ( $status ) + { + Error( "Command '$command' exited with status: $status\n" ); + return( 0 ); + } + else + { + my $sql = "update Events set Executed = 1 where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $event->{Id} ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); + } + return( 1 ); +} + diff --git a/scripts/zmlogrotate.conf b/scripts/zmlogrotate.conf new file mode 100644 index 000000000..730b27bb0 --- /dev/null +++ b/scripts/zmlogrotate.conf @@ -0,0 +1,20 @@ +# First the log files + +/var/log/zm/*log { + weekly + rotate 3 + notifempty + missingok +} + +# Now the weekly db backup + +/var/lib/zm/zm_backup.sql { +weekly +rotate 3 +missingok +compress +postrotate +/usr/bin/zmdbbackup +endscript +} diff --git a/scripts/zmlogrotate.conf.in b/scripts/zmlogrotate.conf.in new file mode 100644 index 000000000..18f11adb8 --- /dev/null +++ b/scripts/zmlogrotate.conf.in @@ -0,0 +1,20 @@ +# First the log files + +/var/log/zm/*log { + weekly + rotate 3 + notifempty + missingok +} + +# Now the weekly db backup + +/var/lib/zm/zm_backup.sql { +weekly +rotate 3 +missingok +compress +postrotate +@BINDIR@/zmdbbackup +endscript +} diff --git a/scripts/zmpkg.pl b/scripts/zmpkg.pl new file mode 100644 index 000000000..632c4023f --- /dev/null +++ b/scripts/zmpkg.pl @@ -0,0 +1,247 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Package Control Script, $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 script is used to start and stop the ZoneMinder package primarily to +# allow command line control for automatic restart on reboot (see zm script) +# +use strict; +use bytes; + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use DBI; +use POSIX; +use Time::HiRes qw/gettimeofday/; + +# Detaint our environment +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); + +my $command = $ARGV[0]; + +my $state; + +my $dbh = zmDbConnect(); + +if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot)$/ ) +{ + if ( $command ) + { + # Check to see if it's a valid run state + my $sql = "select * from States where Name = '$command'"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + if ( $state = $sth->fetchrow_hashref() ) + { + $state->{Name} = $command; + $state->{Definitions} = []; + foreach( split( /,/, $state->{Definition} ) ) + { + my ( $id, $function, $enabled ) = split( /:/, $_ ); + push( @{$state->{Definitions}}, { Id=>$id, Function=>$function, Enabled=>$enabled } ); + } + $command = 'state'; + } + else + { + $command = undef; + } + } + if ( !$command ) + { + print( "Usage: zmpkg.pl \n" ); + exit( -1 ); + } +} + +# Move to the right place +chdir( ZM_PATH_WEB ) or Fatal( "Can't chdir to '".ZM_PATH_WEB."': $!" ); + +my $dbg_id = ""; + +Info( "Command: $command\n" ); + +my $retval = 0; + +if ( $command eq "state" ) +{ + Info( "Updating DB: $state->{Name}\n" ); + my $sql = "select * from Monitors order by Id asc"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + foreach my $definition ( @{$state->{Definitions}} ) + { + if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) + { + $monitor->{NewFunction} = $definition->{Function}; + $monitor->{NewEnabled} = $definition->{Enabled}; + } + } + #next if ( !$monitor->{NewFunction} ); + $monitor->{NewFunction} = 'None' if ( !$monitor->{NewFunction} ); + $monitor->{NewEnabled} = 0 if ( !$monitor->{NewEnabled} ); + if ( $monitor->{Function} ne $monitor->{NewFunction} || $monitor->{Enabled} ne $monitor->{NewEnabled} ) + { + my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} ) or Fatal( "Can't execute: ".$sth->errstr() ); + } + } + $sth->finish(); + + $command = "restart"; +} + +if ( $command =~ /^(?:stop|restart)$/ ) +{ + my $status = runCommand( "zmdc.pl check" ); + + if ( $status eq "running" ) + { + runCommand( "zmdc.pl shutdown" ); + zmMemTidy(); + } + else + { + $retval = 1; + } +} + +runCommand( "zmupdate.pl -f" ); + +if ( $command =~ /^(?:start|restart)$/ ) +{ + my $status = runCommand( "zmdc.pl check" ); + + if ( $status eq "stopped" ) + { + if ( ZM_DYN_DB_VERSION && ZM_DYN_DB_VERSION ne ZM_VERSION ) + { + Fatal( "Version mismatch, system is version ".ZM_VERSION.", database is ".ZM_DYN_DB_VERSION.", please run zmupdate.pl to update." ); + exit( -1 ); + } + + # Recreate the temporary directory if it's been wiped + if ( !-e "/tmp/zm" ) + { + Debug( "Recreating temporary directory '/tmp/zm'" ); + mkdir( "/tmp/zm", 0700 ) or Fatal( "Can't create missing temporary directory '/tmp/zm': $!" ); + my ( $runName ) = getpwuid( $> ); + if ( $runName ne ZM_WEB_USER ) + { + # Not running as web user, so should be root in whch case chown the temporary directory + my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( ZM_WEB_USER ) or Fatal( "Can't get user details for web user '".ZM_WEB_USER."': $!" ); + chown( $webUid, $webGid, "/tmp/zm" ) or Fatal( "Can't change ownership of temporary directory '/tmp/zm' to '".ZM_WEB_USER.":".ZM_WEB_GROUP."': $!" ); + } + } + zmMemTidy(); + runCommand( "zmfix" ); + runCommand( "zmdc.pl startup" ); + + my $sql = "select * from Monitors"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( $monitor->{Function} ne 'None' ) + { + if ( $monitor->{Type} eq 'Local' ) + { + runCommand( "zmdc.pl start zmc -d $monitor->{Device}" ); + } + else + { + runCommand( "zmdc.pl start zmc -m $monitor->{Id}" ); + } + if ( $monitor->{Function} ne 'Monitor' ) + { + if ( ZM_OPT_FRAME_SERVER ) + { + runCommand( "zmdc.pl start zmf -m $monitor->{Id}" ); + } + runCommand( "zmdc.pl start zma -m $monitor->{Id}" ); + } + if ( ZM_OPT_CONTROL ) + { + if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) + { + if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) + { + runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" ); + } + } + } + } + } + $sth->finish(); + + # This is now started unconditionally + runCommand( "zmdc.pl start zmfilter.pl" ); + if ( ZM_RUN_AUDIT ) + { + runCommand( "zmdc.pl start zmaudit.pl -c" ); + } + if ( ZM_OPT_TRIGGERS ) + { + runCommand( "zmdc.pl start zmtrigger.pl" ); + } + if ( ZM_OPT_X10 ) + { + runCommand( "zmdc.pl start zmx10.pl -c start" ); + } + runCommand( "zmdc.pl start zmwatch.pl" ); + if ( ZM_CHECK_FOR_UPDATES ) + { + runCommand( "zmdc.pl start zmupdate.pl -c" ); + } + } + else + { + $retval = 1; + } +} + +if ( $command eq "status" ) +{ + my $status = runCommand( "zmdc.pl check" ); + + print( STDOUT $status."\n" ); +} + +if ( $command eq "logrot" ) +{ + runCommand( "zmdc.pl logrot" ); +} + +exit( $retval ); diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in new file mode 100644 index 000000000..1158a1a29 --- /dev/null +++ b/scripts/zmpkg.pl.in @@ -0,0 +1,247 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Package Control Script, $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 script is used to start and stop the ZoneMinder package primarily to +# allow command line control for automatic restart on reboot (see zm script) +# +use strict; +use bytes; + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use DBI; +use POSIX; +use Time::HiRes qw/gettimeofday/; + +# Detaint our environment +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); + +my $command = $ARGV[0]; + +my $state; + +my $dbh = zmDbConnect(); + +if ( !$command || $command !~ /^(?:start|stop|restart|status|logrot)$/ ) +{ + if ( $command ) + { + # Check to see if it's a valid run state + my $sql = "select * from States where Name = '$command'"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + if ( $state = $sth->fetchrow_hashref() ) + { + $state->{Name} = $command; + $state->{Definitions} = []; + foreach( split( /,/, $state->{Definition} ) ) + { + my ( $id, $function, $enabled ) = split( /:/, $_ ); + push( @{$state->{Definitions}}, { Id=>$id, Function=>$function, Enabled=>$enabled } ); + } + $command = 'state'; + } + else + { + $command = undef; + } + } + if ( !$command ) + { + print( "Usage: zmpkg.pl \n" ); + exit( -1 ); + } +} + +# Move to the right place +chdir( ZM_PATH_WEB ) or Fatal( "Can't chdir to '".ZM_PATH_WEB."': $!" ); + +my $dbg_id = ""; + +Info( "Command: $command\n" ); + +my $retval = 0; + +if ( $command eq "state" ) +{ + Info( "Updating DB: $state->{Name}\n" ); + my $sql = "select * from Monitors order by Id asc"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + foreach my $definition ( @{$state->{Definitions}} ) + { + if ( $monitor->{Id} =~ /^$definition->{Id}$/ ) + { + $monitor->{NewFunction} = $definition->{Function}; + $monitor->{NewEnabled} = $definition->{Enabled}; + } + } + #next if ( !$monitor->{NewFunction} ); + $monitor->{NewFunction} = 'None' if ( !$monitor->{NewFunction} ); + $monitor->{NewEnabled} = 0 if ( !$monitor->{NewEnabled} ); + if ( $monitor->{Function} ne $monitor->{NewFunction} || $monitor->{Enabled} ne $monitor->{NewEnabled} ) + { + my $sql = "update Monitors set Function = ?, Enabled = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $monitor->{NewFunction}, $monitor->{NewEnabled}, $monitor->{Id} ) or Fatal( "Can't execute: ".$sth->errstr() ); + } + } + $sth->finish(); + + $command = "restart"; +} + +if ( $command =~ /^(?:stop|restart)$/ ) +{ + my $status = runCommand( "zmdc.pl check" ); + + if ( $status eq "running" ) + { + runCommand( "zmdc.pl shutdown" ); + zmMemTidy(); + } + else + { + $retval = 1; + } +} + +runCommand( "zmupdate.pl -f" ); + +if ( $command =~ /^(?:start|restart)$/ ) +{ + my $status = runCommand( "zmdc.pl check" ); + + if ( $status eq "stopped" ) + { + if ( ZM_DYN_DB_VERSION && ZM_DYN_DB_VERSION ne ZM_VERSION ) + { + Fatal( "Version mismatch, system is version ".ZM_VERSION.", database is ".ZM_DYN_DB_VERSION.", please run zmupdate.pl to update." ); + exit( -1 ); + } + + # Recreate the temporary directory if it's been wiped + if ( !-e "@ZM_TMPDIR@" ) + { + Debug( "Recreating temporary directory '@ZM_TMPDIR@'" ); + mkdir( "@ZM_TMPDIR@", 0700 ) or Fatal( "Can't create missing temporary directory '@ZM_TMPDIR@': $!" ); + my ( $runName ) = getpwuid( $> ); + if ( $runName ne ZM_WEB_USER ) + { + # Not running as web user, so should be root in whch case chown the temporary directory + my ( $webName, $webPass, $webUid, $webGid ) = getpwnam( ZM_WEB_USER ) or Fatal( "Can't get user details for web user '".ZM_WEB_USER."': $!" ); + chown( $webUid, $webGid, "@ZM_TMPDIR@" ) or Fatal( "Can't change ownership of temporary directory '@ZM_TMPDIR@' to '".ZM_WEB_USER.":".ZM_WEB_GROUP."': $!" ); + } + } + zmMemTidy(); + runCommand( "zmfix" ); + runCommand( "zmdc.pl startup" ); + + my $sql = "select * from Monitors"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( $monitor->{Function} ne 'None' ) + { + if ( $monitor->{Type} eq 'Local' ) + { + runCommand( "zmdc.pl start zmc -d $monitor->{Device}" ); + } + else + { + runCommand( "zmdc.pl start zmc -m $monitor->{Id}" ); + } + if ( $monitor->{Function} ne 'Monitor' ) + { + if ( ZM_OPT_FRAME_SERVER ) + { + runCommand( "zmdc.pl start zmf -m $monitor->{Id}" ); + } + runCommand( "zmdc.pl start zma -m $monitor->{Id}" ); + } + if ( ZM_OPT_CONTROL ) + { + if ( $monitor->{Function} eq 'Modect' || $monitor->{Function} eq 'Mocord' ) + { + if ( $monitor->{Controllable} && $monitor->{TrackMotion} ) + { + runCommand( "zmdc.pl start zmtrack.pl -m $monitor->{Id}" ); + } + } + } + } + } + $sth->finish(); + + # This is now started unconditionally + runCommand( "zmdc.pl start zmfilter.pl" ); + if ( ZM_RUN_AUDIT ) + { + runCommand( "zmdc.pl start zmaudit.pl -c" ); + } + if ( ZM_OPT_TRIGGERS ) + { + runCommand( "zmdc.pl start zmtrigger.pl" ); + } + if ( ZM_OPT_X10 ) + { + runCommand( "zmdc.pl start zmx10.pl -c start" ); + } + runCommand( "zmdc.pl start zmwatch.pl" ); + if ( ZM_CHECK_FOR_UPDATES ) + { + runCommand( "zmdc.pl start zmupdate.pl -c" ); + } + } + else + { + $retval = 1; + } +} + +if ( $command eq "status" ) +{ + my $status = runCommand( "zmdc.pl check" ); + + print( STDOUT $status."\n" ); +} + +if ( $command eq "logrot" ) +{ + runCommand( "zmdc.pl logrot" ); +} + +exit( $retval ); diff --git a/scripts/zmtrack.pl b/scripts/zmtrack.pl new file mode 100644 index 000000000..c80277005 --- /dev/null +++ b/scripts/zmtrack.pl @@ -0,0 +1,205 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Experimental PTZ Tracking Script, $Date: 2009-06-08 10:11:56 +0100 (Mon, 08 Jun 2009) $, $Revision: 2908 $ +# 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 script is used to trigger and cancel alarms from external sources +# using an arbitrary text based format +# +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant SLEEP_TIME => 10000; # In microseconds + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use ZoneMinder; +use DBI; +use POSIX; +use Data::Dumper; +use Getopt::Long; +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $mid = 0; + +sub Usage +{ + print( " + Usage: zmtrack.pl -m ,--monitor=] + Parameters are :- + -m, --monitor= - Id of the monitor to track + "); + exit( -1 ); +} + +if ( !GetOptions( 'monitor=s'=>\$mid ) ) +{ + Usage(); +} + +logInit(); +logSetSignal(); + +my ( $detaint_mid ) = $mid =~ /^(\d+)$/; +$mid = $detaint_mid; + +print( "Tracker daemon $mid (experimental) starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + +my $dbh = zmDbConnect(); + +my $sql = "select C.*,M.* from Monitors as M left join Controls as C on M.ControlId = C.Id where M.Id = ?"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + +my $res = $sth->execute( $mid ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); +my $monitor = $sth->fetchrow_hashref(); + +if ( !$monitor ) +{ + print( "Can't find monitor '$mid'\n" ); + exit( -1 ); +} +if ( !$monitor->{Controllable} ) +{ + print( "Monitor '$mid' is not controllable\n" ); + exit( -1 ); +} +if ( !$monitor->{TrackMotion} ) +{ + print( "Monitor '$mid' is not configured to track motion\n" ); + exit( -1 ); +} + +if ( !$monitor->{CanMoveMap} ) +{ + print( "Monitor '$mid' cannot move in map mode" ); + if ( $monitor->{CanMoveRel} ) + { + print( ", falling back to pseudo map mode\n" ); + } + else + { + print( "\n" ); + exit( -1 ); + } +} + +Debug( "Found monitor for id '$monitor'\n" ); +exit( -1 ) if ( !zmMemVerify( $monitor ) ); + +sub Suspend +{ + my $monitor = shift; + zmMonitorSuspend( $monitor ); +} + +sub Resume +{ + my $monitor = shift; + sleep( $monitor->{TrackDelay} ); + zmMonitorResume( $monitor ); +} + +sub Track +{ + my $monitor = shift; + my ( $x, $y ) = @_; + my ( $detaint_x ) = $x =~ /^(\d+)$/; $x = $detaint_x; + my ( $detaint_y ) = $y =~ /^(\d+)$/; $y = $detaint_y; + + my $ctrlCommand = ZM_PATH_BIN."/zmcontrol.pl -i ".$monitor->{Id}; + $ctrlCommand .= " --command=".($monitor->{CanMoveMap}?"moveMap":"movePseudoMap")." --xcoord=$x --ycoord=$y"; + executeShellCommand( $ctrlCommand ); +} + +sub Return +{ + my $monitor = shift; + + my $ctrlCommand = ZM_PATH_BIN."/zmcontrol.pl -i ".$monitor->{Id}; + if ( $monitor->{ReturnLocation} > 0 ) + { + $ctrlCommand .= " --command=presetGoto --preset=".$monitor->{ReturnLocation}; + } + else + { + $ctrlCommand .= " --command=presetHome"; + } + executeShellCommand( $ctrlCommand ); +} + +my $last_alarm = 0; +if ( ($monitor->{ReturnLocation} >= 0) ) +{ + Suspend( $monitor ); + Return( $monitor ); + Resume( $monitor ); +} + +my $alarmed = undef; +while( 1 ) +{ + if ( zmIsAlarmed( $monitor ) ) + { + my ( $alarm_x, $alarm_y ) = zmGetAlarmLocation( $monitor ); + if ( $alarm_x >= 0 && $alarm_y >= 0 ) + { + Debug( "Got alarm at $alarm_x, $alarm_y\n" ); + Suspend( $monitor ); + Track( $monitor, $alarm_x, $alarm_y ); + Resume( $monitor ); + $last_alarm = time(); + $alarmed = !undef; + } + } + else + { + if ( logDebugging() && $alarmed ) + { + print( "Left alarm state\n" ); + $alarmed = undef; + } + if ( ($monitor->{ReturnLocation} >= 0) && ($last_alarm > 0) && ((time()-$last_alarm) > $monitor->{ReturnDelay}) ) + { + Debug( "Returning to location ".$monitor->{ReturnLocation}."\n" ); + Suspend( $monitor ); + Return( $monitor ); + Resume( $monitor ); + $last_alarm = 0; + } + } + usleep( SLEEP_TIME ); +} diff --git a/scripts/zmtrack.pl.in b/scripts/zmtrack.pl.in new file mode 100644 index 000000000..c80277005 --- /dev/null +++ b/scripts/zmtrack.pl.in @@ -0,0 +1,205 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Experimental PTZ Tracking Script, $Date: 2009-06-08 10:11:56 +0100 (Mon, 08 Jun 2009) $, $Revision: 2908 $ +# 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 script is used to trigger and cancel alarms from external sources +# using an arbitrary text based format +# +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant SLEEP_TIME => 10000; # In microseconds + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use ZoneMinder; +use DBI; +use POSIX; +use Data::Dumper; +use Getopt::Long; +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $mid = 0; + +sub Usage +{ + print( " + Usage: zmtrack.pl -m ,--monitor=] + Parameters are :- + -m, --monitor= - Id of the monitor to track + "); + exit( -1 ); +} + +if ( !GetOptions( 'monitor=s'=>\$mid ) ) +{ + Usage(); +} + +logInit(); +logSetSignal(); + +my ( $detaint_mid ) = $mid =~ /^(\d+)$/; +$mid = $detaint_mid; + +print( "Tracker daemon $mid (experimental) starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + +my $dbh = zmDbConnect(); + +my $sql = "select C.*,M.* from Monitors as M left join Controls as C on M.ControlId = C.Id where M.Id = ?"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + +my $res = $sth->execute( $mid ) or Fatal( "Can't execute '$sql': ".$sth->errstr() ); +my $monitor = $sth->fetchrow_hashref(); + +if ( !$monitor ) +{ + print( "Can't find monitor '$mid'\n" ); + exit( -1 ); +} +if ( !$monitor->{Controllable} ) +{ + print( "Monitor '$mid' is not controllable\n" ); + exit( -1 ); +} +if ( !$monitor->{TrackMotion} ) +{ + print( "Monitor '$mid' is not configured to track motion\n" ); + exit( -1 ); +} + +if ( !$monitor->{CanMoveMap} ) +{ + print( "Monitor '$mid' cannot move in map mode" ); + if ( $monitor->{CanMoveRel} ) + { + print( ", falling back to pseudo map mode\n" ); + } + else + { + print( "\n" ); + exit( -1 ); + } +} + +Debug( "Found monitor for id '$monitor'\n" ); +exit( -1 ) if ( !zmMemVerify( $monitor ) ); + +sub Suspend +{ + my $monitor = shift; + zmMonitorSuspend( $monitor ); +} + +sub Resume +{ + my $monitor = shift; + sleep( $monitor->{TrackDelay} ); + zmMonitorResume( $monitor ); +} + +sub Track +{ + my $monitor = shift; + my ( $x, $y ) = @_; + my ( $detaint_x ) = $x =~ /^(\d+)$/; $x = $detaint_x; + my ( $detaint_y ) = $y =~ /^(\d+)$/; $y = $detaint_y; + + my $ctrlCommand = ZM_PATH_BIN."/zmcontrol.pl -i ".$monitor->{Id}; + $ctrlCommand .= " --command=".($monitor->{CanMoveMap}?"moveMap":"movePseudoMap")." --xcoord=$x --ycoord=$y"; + executeShellCommand( $ctrlCommand ); +} + +sub Return +{ + my $monitor = shift; + + my $ctrlCommand = ZM_PATH_BIN."/zmcontrol.pl -i ".$monitor->{Id}; + if ( $monitor->{ReturnLocation} > 0 ) + { + $ctrlCommand .= " --command=presetGoto --preset=".$monitor->{ReturnLocation}; + } + else + { + $ctrlCommand .= " --command=presetHome"; + } + executeShellCommand( $ctrlCommand ); +} + +my $last_alarm = 0; +if ( ($monitor->{ReturnLocation} >= 0) ) +{ + Suspend( $monitor ); + Return( $monitor ); + Resume( $monitor ); +} + +my $alarmed = undef; +while( 1 ) +{ + if ( zmIsAlarmed( $monitor ) ) + { + my ( $alarm_x, $alarm_y ) = zmGetAlarmLocation( $monitor ); + if ( $alarm_x >= 0 && $alarm_y >= 0 ) + { + Debug( "Got alarm at $alarm_x, $alarm_y\n" ); + Suspend( $monitor ); + Track( $monitor, $alarm_x, $alarm_y ); + Resume( $monitor ); + $last_alarm = time(); + $alarmed = !undef; + } + } + else + { + if ( logDebugging() && $alarmed ) + { + print( "Left alarm state\n" ); + $alarmed = undef; + } + if ( ($monitor->{ReturnLocation} >= 0) && ($last_alarm > 0) && ((time()-$last_alarm) > $monitor->{ReturnDelay}) ) + { + Debug( "Returning to location ".$monitor->{ReturnLocation}."\n" ); + Suspend( $monitor ); + Return( $monitor ); + Resume( $monitor ); + $last_alarm = 0; + } + } + usleep( SLEEP_TIME ); +} diff --git a/scripts/zmtrigger.pl b/scripts/zmtrigger.pl new file mode 100644 index 000000000..204d95153 --- /dev/null +++ b/scripts/zmtrigger.pl @@ -0,0 +1,440 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder External Trigger Script, $Date: 2008-07-25 10:48:16 +0100 (Fri, 25 Jul 2008) $, $Revision: 2612 $ +# 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 script is used to trigger and cancel alarms from external connections +# using an arbitrary text based format +# +# ========================================================================== +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; +use constant MONITOR_RELOAD_INTERVAL => 300; +use constant SELECT_TIMEOUT => 0.25; + +# ========================================================================== +# +# Channel/Connection Modules +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use ZoneMinder::Trigger::Channel::Inet; +use ZoneMinder::Trigger::Channel::Unix; +use ZoneMinder::Trigger::Channel::Serial; +use ZoneMinder::Trigger::Connection; + +my @connections; +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan1", channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), mode=>"rw" ) ); +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan2", channel=>ZoneMinder::Trigger::Channel::Unix->new( path=>ZM_PATH_SOCKS.'/zmtrigger.sock' ), mode=>"rw" ) ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) ); +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) ); + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use DBI; +#use Socket; +use Data::Dumper; +use POSIX qw( EINTR ); +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); +logSetSignal(); + +Info( "Trigger daemon starting\n" ); + +my $dbh = zmDbConnect(); + +my $base_rin = ''; +foreach my $connection ( @connections ) +{ + Info( "Opening connection '$connection->{name}'\n" ); + $connection->open(); +} + +my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; +my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; +my @out_connections = grep { $_->output() } @connections; + +foreach my $connection ( @in_select_connections ) +{ + vec( $base_rin, $connection->fileno(), 1 ) = 1; +} + +my %spawned_connections; +my %monitors; + +my $monitor_reload_time = 0; + +$! = undef; +my $rin = ''; +my $win = $rin; +my $ein = $win; +my $timeout = SELECT_TIMEOUT; +my %actions; +while( 1 ) +{ + $rin = $base_rin; + # Add the file descriptors of any spawned connections + foreach my $fileno ( keys(%spawned_connections) ) + { + vec( $rin, $fileno, 1 ) = 1; + } + + my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); + if ( $nfound > 0 ) + { + Debug( "Got input from $nfound connections\n" ); + foreach my $connection ( @in_select_connections ) + { + if ( vec( $rout, $connection->fileno(), 1 ) ) + { + Debug( "Got input from connection ".$connection->name()." (".$connection->fileno().")\n" ); + if ( $connection->spawns() ) + { + my $new_connection = $connection->accept(); + $spawned_connections{$new_connection->fileno()} = $new_connection; + Debug( "Added new spawned connection (".$new_connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" ); + } + else + { + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + } + } + foreach my $connection ( values(%spawned_connections) ) + { + if ( vec( $rout, $connection->fileno(), 1 ) ) + { + Debug( "Got input from spawned connection ".$connection->name()." (".$connection->fileno().")\n" ); + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + else + { + delete( $spawned_connections{$connection->fileno()} ); + Debug( "Removed spawned connection (".$connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" ); + $connection->close(); + } + } + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EINTR ) + { + # Do nothing + } + else + { + Fatal( "Can't select: $!" ); + } + } + + # Check polled connections + foreach my $connection ( @in_poll_connections ) + { + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + + # Check for alarms that might have happened + my @out_messages; + foreach my $monitor ( values(%monitors) ) + { + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] ); + + #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); + #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); + if ( $state == STATE_ALARM || $state == STATE_ALERT ) # In alarm state + { + if ( !defined($monitor->{LastEvent}) || ($last_event != $monitor->{LastEvent}) ) # A new event + { + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + } + else # The same one as last time, so ignore it + { + # Do nothing + } + } + elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Out of alarm state + { + push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); + } + elsif ( defined($monitor->{LastEvent}) && ($last_event != $monitor->{LastEvent}) ) # We've missed a whole event + { + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); + } + $monitor->{LastState} = $state; + $monitor->{LastEvent} = $last_event; + } + foreach my $connection ( @out_connections ) + { + if ( $connection->canWrite() ) + { + $connection->putMessages( \@out_messages ); + } + } + foreach my $connection ( values(%spawned_connections) ) + { + if ( $connection->canWrite() ) + { + $connection->putMessages( \@out_messages ); + } + } + + Debug( "Checking for timed actions\n" ) if ( int(keys(%actions)) ); + my $now = time(); + foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) + { + Info( "Found actions expiring at $action_time\n" ); + foreach my $action ( @{$actions{$action_time}} ) + { + my $connection = $action->{connection}; + my $message = $action->{message}; + Info( "Found action '$message'\n" ); + handleMessage( $connection, $message ); + } + delete( $actions{$action_time} ); + } + + # Allow connections to do their own timed actions + foreach my $connection ( @connections ) + { + my $messages = $connection->timedActions(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + foreach my $connection ( values(%spawned_connections) ) + { + my $messages = $connection->timedActions(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + + # If necessary reload monitors + if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ) + { + foreach my $monitor ( values(%monitors) ) + { + # Free up any used memory handle + zmMemInvalidate( $monitor ); + } + loadMonitors(); + } +} +Info( "Trigger daemon exiting\n" ); +exit; + +sub loadMonitors +{ + Debug( "Loading monitors\n" ); + $monitor_reload_time = time(); + + my %new_monitors = (); + + my $sql = "select * from Monitors where find_in_set( Function, 'Modect,Mocord,Nodect' )"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok + + if ( defined($monitors{$monitor->{Id}}->{LastState}) ) + { + $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; + } + else + { + $monitor->{LastState} = zmGetMonitorState( $monitor ); + } + if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) + { + $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; + } + else + { + $monitor->{LastEvent} = zmGetLastEvent( $monitor ); + } + $new_monitors{$monitor->{Id}} = $monitor; + } + %monitors = %new_monitors; +} + +sub handleMessage +{ + my $connection = shift; + my $message = shift; + + my ( $id, $action, $score, $cause, $text, $showtext ) = split( /\|/, $message ); + $score = 0 if ( !defined($score) ); + $cause = "" if ( !defined($cause) ); + $text = "" if ( !defined($text) ); + + my $monitor = $monitors{$id}; + if ( !$monitor ) + { + Warning( "Can't find monitor '$id' for message '$message'\n" ); + return; + } + Debug( "Found monitor for id '$id'\n" ); + + next if ( !zmMemVerify( $monitor ) ); + + Debug( "Handling action '$action'\n" ); + if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) + { + my $state = $1; + my $delay = $2; + if ( $state eq "enable" ) + { + zmMonitorEnable( $monitor ); + } + else + { + zmMonitorDisable( $monitor ); + } + # Force a reload + $monitor_reload_time = 0; + Info( "Set monitor to $state\n" ); + if ( $delay ) + { + my $action_time = time()+$delay; + my $action_text = $id."|".(($state eq "enable")?"disable":"enable"); + 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+))?$/ ) + { + next if ( !$monitor->{Enabled} ); + + my $trigger = $1; + my $delay = $2; + my $trigger_data; + if ( $trigger eq "on" ) + { + zmTriggerEventOn( $monitor, $score, $cause, $text ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger' '$cause'\n" ); + } + elsif ( $trigger eq "off" ) + { + 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 ); + } + 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" ) + { + zmTriggerEventCancel( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Cancelled event\n" ); + } + elsif( $action eq "show" ) + { + zmTriggerShowtext( $monitor, $showtext ); + Info( "Updated show text to '$showtext'\n" ); + } + else + { + Error( "Unrecognised action '$action' in message '$message'\n" ); + } +} diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in new file mode 100644 index 000000000..11c5c9a29 --- /dev/null +++ b/scripts/zmtrigger.pl.in @@ -0,0 +1,440 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder External Trigger Script, $Date: 2008-07-25 10:48:16 +0100 (Fri, 25 Jul 2008) $, $Revision: 2612 $ +# 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 script is used to trigger and cancel alarms from external connections +# using an arbitrary text based format +# +# ========================================================================== +use strict; +use bytes; + +# ========================================================================== +# +# User config +# +# ========================================================================== + +use constant MAX_CONNECT_DELAY => 10; +use constant MONITOR_RELOAD_INTERVAL => 300; +use constant SELECT_TIMEOUT => 0.25; + +# ========================================================================== +# +# Channel/Connection Modules +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use ZoneMinder::Trigger::Channel::Inet; +use ZoneMinder::Trigger::Channel::Unix; +use ZoneMinder::Trigger::Channel::Serial; +use ZoneMinder::Trigger::Connection; + +my @connections; +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan1", channel=>ZoneMinder::Trigger::Channel::Inet->new( port=>6802 ), mode=>"rw" ) ); +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan2", channel=>ZoneMinder::Trigger::Channel::Unix->new( path=>ZM_PATH_SOCKS.'/zmtrigger.sock' ), mode=>"rw" ) ); +#push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan3", channel=>ZoneMinder::Trigger::Channel::File->new( path=>'/tmp/zmtrigger.out' ), mode=>"w" ) ); +push( @connections, ZoneMinder::Trigger::Connection->new( name=>"Chan4", channel=>ZoneMinder::Trigger::Channel::Serial->new( path=>'/dev/ttyS0' ), mode=>"rw" ) ); + +# ========================================================================== +# +# Don't change anything from here on down +# +# ========================================================================== + +use DBI; +#use Socket; +use Data::Dumper; +use POSIX qw( EINTR ); +use Time::HiRes qw( usleep ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); +logSetSignal(); + +Info( "Trigger daemon starting\n" ); + +my $dbh = zmDbConnect(); + +my $base_rin = ''; +foreach my $connection ( @connections ) +{ + Info( "Opening connection '$connection->{name}'\n" ); + $connection->open(); +} + +my @in_select_connections = grep { $_->input() && $_->selectable() } @connections; +my @in_poll_connections = grep { $_->input() && !$_->selectable() } @connections; +my @out_connections = grep { $_->output() } @connections; + +foreach my $connection ( @in_select_connections ) +{ + vec( $base_rin, $connection->fileno(), 1 ) = 1; +} + +my %spawned_connections; +my %monitors; + +my $monitor_reload_time = 0; + +$! = undef; +my $rin = ''; +my $win = $rin; +my $ein = $win; +my $timeout = SELECT_TIMEOUT; +my %actions; +while( 1 ) +{ + $rin = $base_rin; + # Add the file descriptors of any spawned connections + foreach my $fileno ( keys(%spawned_connections) ) + { + vec( $rin, $fileno, 1 ) = 1; + } + + my $nfound = select( my $rout = $rin, undef, my $eout = $ein, $timeout ); + if ( $nfound > 0 ) + { + Debug( "Got input from $nfound connections\n" ); + foreach my $connection ( @in_select_connections ) + { + if ( vec( $rout, $connection->fileno(), 1 ) ) + { + Debug( "Got input from connection ".$connection->name()." (".$connection->fileno().")\n" ); + if ( $connection->spawns() ) + { + my $new_connection = $connection->accept(); + $spawned_connections{$new_connection->fileno()} = $new_connection; + Debug( "Added new spawned connection (".$new_connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" ); + } + else + { + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + } + } + foreach my $connection ( values(%spawned_connections) ) + { + if ( vec( $rout, $connection->fileno(), 1 ) ) + { + Debug( "Got input from spawned connection ".$connection->name()." (".$connection->fileno().")\n" ); + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + else + { + delete( $spawned_connections{$connection->fileno()} ); + Debug( "Removed spawned connection (".$connection->fileno()."), ".int(keys(%spawned_connections))." spawned connections\n" ); + $connection->close(); + } + } + } + } + elsif ( $nfound < 0 ) + { + if ( $! == EINTR ) + { + # Do nothing + } + else + { + Fatal( "Can't select: $!" ); + } + } + + # Check polled connections + foreach my $connection ( @in_poll_connections ) + { + my $messages = $connection->getMessages(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + + # Check for alarms that might have happened + my @out_messages; + foreach my $monitor ( values(%monitors) ) + { + my ( $state, $last_event ) = zmMemRead( $monitor, [ "shared_data:state", "shared_data:last_event" ] ); + + #print( "$monitor->{Id}: S:$state, LE:$last_event\n" ); + #print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}\n" ); + if ( $state == STATE_ALARM || $state == STATE_ALERT ) # In alarm state + { + if ( !defined($monitor->{LastEvent}) || ($last_event != $monitor->{LastEvent}) ) # A new event + { + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + } + else # The same one as last time, so ignore it + { + # Do nothing + } + } + elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Out of alarm state + { + push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); + } + elsif ( defined($monitor->{LastEvent}) && ($last_event != $monitor->{LastEvent}) ) # We've missed a whole event + { + push( @out_messages, $monitor->{Id}."|on|".time()."|".$last_event ); + push( @out_messages, $monitor->{Id}."|off|".time()."|".$last_event ); + } + $monitor->{LastState} = $state; + $monitor->{LastEvent} = $last_event; + } + foreach my $connection ( @out_connections ) + { + if ( $connection->canWrite() ) + { + $connection->putMessages( \@out_messages ); + } + } + foreach my $connection ( values(%spawned_connections) ) + { + if ( $connection->canWrite() ) + { + $connection->putMessages( \@out_messages ); + } + } + + Debug( "Checking for timed actions\n" ) if ( int(keys(%actions)) ); + my $now = time(); + foreach my $action_time ( sort( grep { $_ < $now } keys( %actions ) ) ) + { + Info( "Found actions expiring at $action_time\n" ); + foreach my $action ( @{$actions{$action_time}} ) + { + my $connection = $action->{connection}; + my $message = $action->{message}; + Info( "Found action '$message'\n" ); + handleMessage( $connection, $message ); + } + delete( $actions{$action_time} ); + } + + # Allow connections to do their own timed actions + foreach my $connection ( @connections ) + { + my $messages = $connection->timedActions(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + foreach my $connection ( values(%spawned_connections) ) + { + my $messages = $connection->timedActions(); + if ( defined($messages) ) + { + foreach my $message ( @$messages ) + { + handleMessage( $connection, $message ); + } + } + } + + # If necessary reload monitors + if ( (time() - $monitor_reload_time) > MONITOR_RELOAD_INTERVAL ) + { + foreach my $monitor ( values(%monitors) ) + { + # Free up any used memory handle + zmMemInvalidate( $monitor ); + } + loadMonitors(); + } +} +Info( "Trigger daemon exiting\n" ); +exit; + +sub loadMonitors +{ + Debug( "Loading monitors\n" ); + $monitor_reload_time = time(); + + my %new_monitors = (); + + my $sql = "select * from Monitors where find_in_set( Function, 'Modect,Mocord,Nodect' )"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok + + if ( defined($monitors{$monitor->{Id}}->{LastState}) ) + { + $monitor->{LastState} = $monitors{$monitor->{Id}}->{LastState}; + } + else + { + $monitor->{LastState} = zmGetMonitorState( $monitor ); + } + if ( defined($monitors{$monitor->{Id}}->{LastEvent}) ) + { + $monitor->{LastEvent} = $monitors{$monitor->{Id}}->{LastEvent}; + } + else + { + $monitor->{LastEvent} = zmGetLastEvent( $monitor ); + } + $new_monitors{$monitor->{Id}} = $monitor; + } + %monitors = %new_monitors; +} + +sub handleMessage +{ + my $connection = shift; + my $message = shift; + + my ( $id, $action, $score, $cause, $text, $showtext ) = split( /\|/, $message ); + $score = 0 if ( !defined($score) ); + $cause = "" if ( !defined($cause) ); + $text = "" if ( !defined($text) ); + + my $monitor = $monitors{$id}; + if ( !$monitor ) + { + Warning( "Can't find monitor '$id' for message '$message'\n" ); + return; + } + Debug( "Found monitor for id '$id'\n" ); + + next if ( !zmMemVerify( $monitor ) ); + + Debug( "Handling action '$action'\n" ); + if ( $action =~ /^(enable|disable)(?:\+(\d+))?$/ ) + { + my $state = $1; + my $delay = $2; + if ( $state eq "enable" ) + { + zmMonitorEnable( $monitor ); + } + else + { + zmMonitorDisable( $monitor ); + } + # Force a reload + $monitor_reload_time = 0; + Info( "Set monitor to $state\n" ); + if ( $delay ) + { + my $action_time = time()+$delay; + my $action_text = $id."|".(($state eq "enable")?"disable":"enable"); + 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+))?$/ ) + { + next if ( !$monitor->{Enabled} ); + + my $trigger = $1; + my $delay = $2; + my $trigger_data; + if ( $trigger eq "on" ) + { + zmTriggerEventOn( $monitor, $score, $cause, $text ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Trigger '$trigger' '$cause'\n" ); + } + elsif ( $trigger eq "off" ) + { + 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 ); + } + 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" ) + { + zmTriggerEventCancel( $monitor ); + zmTriggerShowtext( $monitor, $showtext ) if defined($showtext); + Info( "Cancelled event\n" ); + } + elsif( $action eq "show" ) + { + zmTriggerShowtext( $monitor, $showtext ); + Info( "Updated show text to '$showtext'\n" ); + } + else + { + Error( "Unrecognised action '$action' in message '$message'\n" ); + } +} diff --git a/scripts/zmupdate.pl b/scripts/zmupdate.pl new file mode 100644 index 000000000..7aa64ac3a --- /dev/null +++ b/scripts/zmupdate.pl @@ -0,0 +1,984 @@ +#!/usr/bin/perl -w +# +# ========================================================================== +# +# ZoneMinder Update Script, $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 script just checks what the most recent release of ZoneMinder is +# at the the moment. It will eventually be responsible for applying and +# configuring upgrades etc, including on the fly upgrades. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant CHECK_INTERVAL => (1*24*60*60); # Interval between version checks + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder::Base qw(:all); +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); +use ZoneMinder::General qw(:all); +use ZoneMinder::Database qw(:all); +use ZoneMinder::ConfigAdmin qw( :functions ); +use POSIX; +use DBI; +use Getopt::Long; +use Data::Dumper; + +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $web_uid = (getpwnam( ZM_WEB_USER ))[2]; +my $use_log = (($> == 0) || ($> == $web_uid)); + +logInit( toFile=>$use_log?DEBUG:NOLOG ); +logSetSignal(); + +my $interactive = 1; +my $check = 0; +my $freshen = 0; +my $rename = 0; +my $zoneFix = 0; +my $migrateEvents = 0; +my $version = ''; +my $dbUser = ZM_DB_USER; +my $dbPass = ZM_DB_PASS; +my $updateDir = ''; +sub Usage +{ + print( " +Usage: zmupdate.pl <-c,--check|-f,--freshen|-v,--version=> [-u -p]> +Parameters are :- +-c, --check - Check for updated versions of ZoneMinder +-f, --freshen - Freshen the configuration in the database. Equivalent of old zmconfig.pl -noi +-v, --version= - Force upgrade to the current version from +-u, --user= - Alternate DB user with privileges to alter DB +-p, --pass= - Password of alternate DB user with privileges to alter DB +-d,--dir= - Directory containing update files if not in default build location +"); + exit( -1 ); +} + +if ( !GetOptions( 'check'=>\$check, 'freshen'=>\$freshen, 'rename'=>\$rename, 'zone-fix'=>\$zoneFix, 'migrate-events'=>\$migrateEvents, 'version=s'=>\$version, 'interactive!'=>\$interactive, 'user:s'=>\$dbUser, 'pass:s'=>\$dbPass, 'dir:s'=>\$updateDir ) ) +{ + Usage(); +} + +if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) +{ + if ( ZM_DYN_DB_VERSION ) + { + $version = ZM_DYN_DB_VERSION; + } + else + { + print( STDERR "Please give a valid option\n" ); + Usage(); + } +} + +if ( ($check + $freshen + $rename + $zoneFix + $migrateEvents + ($version?1:0)) > 1 ) +{ + print( STDERR "Please give only one option\n" ); + Usage(); +} + +if ( $check && ZM_CHECK_FOR_UPDATES ) +{ + print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + my $dbh = zmDbConnect(); + + my $currVersion = ZM_DYN_CURR_VERSION; + my $lastVersion = ZM_DYN_LAST_VERSION; + my $lastCheck = ZM_DYN_LAST_CHECK; + + if ( !$currVersion ) + { + $currVersion = ZM_VERSION; + + my $sql = "update Config set Value = ? where Name = 'ZM_DYN_CURR_VERSION'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( "$currVersion" ) or die( "Can't execute: ".$sth->errstr() ); + } + zmDbDisconnect(); + + while( 1 ) + { + my $now = time(); + if ( !$lastVersion || !$lastCheck || (($now-$lastCheck) > CHECK_INTERVAL) ) + { + $dbh = zmDbConnect(); + + Info( "Checking for updates\n" ); + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->agent( "ZoneMinder Update Agent/".ZM_VERSION ); + if ( eval('defined(ZM_UPDATE_CHECK_PROXY)') ) + { + no strict 'subs'; + if ( ZM_UPDATE_CHECK_PROXY ) + { + $ua->proxy( "http", ZM_UPDATE_CHECK_PROXY ); + } + use strict 'subs'; + } + my $req = HTTP::Request->new( GET=>'http://www.zoneminder.com/version' ); + my $res = $ua->request($req); + + if ( $res->is_success ) + { + $lastVersion = $res->content; + chomp($lastVersion); + $lastCheck = $now; + + Info( "Got version: '".$lastVersion."'\n" ); + + my $lv_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_VERSION'"; + my $lv_sth = $dbh->prepare_cached( $lv_sql ) or die( "Can't prepare '$lv_sql': ".$dbh->errstr() ); + my $lv_res = $lv_sth->execute( $lastVersion ) or die( "Can't execute: ".$lv_sth->errstr() ); + + my $lc_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_CHECK'"; + my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() ); + my $lc_res = $lc_sth->execute( $lastCheck ) or die( "Can't execute: ".$lc_sth->errstr() ); + } + else + { + Error( "Error check failed: '".$res->status_line()."'\n" ); + } + zmDbDisconnect(); + } + sleep( 3600 ); + } + print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); +} +if ( $rename ) +{ + require File::Find; + + chdir( EVENT_PATH ); + + sub renameImage + { + my $file = $_; + + # Ignore directories + if ( -d $file ) + { + print( "Checking directory '$file'\n" ); + return; + } + if ( $file !~ /(capture|analyse)-(\d+)(\.jpg)/ ) + { + return; + } + my $newFile = "$2-$1$3"; + + print( "Renaming '$file' to '$newFile'\n" ); + rename( $file, $newFile ) or warn( "Can't rename '$file' to '$newFile'" ); + } + + File::Find::find( \&renameImage, '.' ); +} +if ( $zoneFix ) +{ + require DBI; + + my $dbh = zmDbConnect(); + + my $sql = "select Z.*, M.Width as MonitorWidth, M.Height as MonitorHeight from Zones as Z inner join Monitors as M on Z.MonitorId = M.Id where Z.Units = 'Percent'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @zones; + while( my $zone = $sth->fetchrow_hashref() ) + { + push( @zones, $zone ); + } + $sth->finish(); + + foreach my $zone ( @zones ) + { + my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100; + my $zone_height = (($zone->{HiY}*$zone->{MonitorHeight})-($zone->{LoY}*$zone->{MonitorHeight}))/100; + my $zone_area = $zone_width * $zone_height; + my $monitor_area = $zone->{MonitorWidth} * $zone->{MonitorHeight}; + my $sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( + ($zone->{MinAlarmPixels}*$monitor_area)/$zone_area, + ($zone->{MaxAlarmPixels}*$monitor_area)/$zone_area, + ($zone->{MinFilterPixels}*$monitor_area)/$zone_area, + ($zone->{MaxFilterPixels}*$monitor_area)/$zone_area, + ($zone->{MinBlobPixels}*$monitor_area)/$zone_area, + ($zone->{MaxBlobPixels}*$monitor_area)/$zone_area, + $zone->{Id} + ) or die( "Can't execute: ".$sth->errstr() ); + } +} +if ( $migrateEvents ) +{ + my $webUid = (getpwnam( ZM_WEB_USER ))[2]; + my $webGid = (getgrnam( ZM_WEB_USER ))[2]; + + if ( !(($> == 0) || ($> == $webUid)) ) + { + print( "Error, migrating events can only be done as user root or ".ZM_WEB_USER.".\n" ); + exit( -1 ); + } + + # Run as web user/group + $( = $webGid; + $) = $webGid; + $< = $webUid; + $> = $webUid; + + print( "\nAbout to convert saved events to deep storage, please ensure that ZoneMinder is fully stopped before proceeding.\nThis process is not easily reversible. Are you sure you wish to proceed?\n\nPress 'y' to continue or 'n' to abort : " ); + my $response = ; + chomp( $response ); + while ( $response !~ /^[yYnN]$/ ) + { + print( "Please press 'y' to continue or 'n' to abort only : " ); + $response = ; + chomp( $response ); + } + + if ( $response =~ /^[yY]$/ ) + { + print( "Converting all events to deep storage.\n" ); + + chdir( ZM_PATH_WEB ); + my $dbh = zmDbConnect(); + my $sql = "select *, unix_timestamp(StartTime) as UnixStartTime from Events"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute(); + if ( !$res ) + { + Fatal( "Can't fetch Events: ".$sth->errstr() ); + } + + while( my $event = $sth->fetchrow_hashref() ) + { + my $oldEventPath = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id}; + + if ( !-d $oldEventPath ) + { + print( "Warning, can't find old event path '$oldEventPath', already converted?\n" ); + next; + } + + print( "Converting event ".$event->{Id}."\n" ); + my $newDatePath = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.strftime( "%y/%m/%d", localtime($event->{UnixStartTime}) ); + my $newTimePath = strftime( "%H/%M/%S", localtime($event->{UnixStartTime}) ); + my $newEventPath = $newDatePath.'/'.$newTimePath; + ( my $truncEventPath = $newEventPath ) =~ s|/\d+$||; + makePath( $truncEventPath, ZM_PATH_WEB ); + my $idLink = $newDatePath.'/.'.$event->{Id}; + symlink( $newTimePath, $idLink ) or die( "Can't symlink $newTimePath -> $idLink: $!" ); + rename( $oldEventPath, $newEventPath ) or die( "Can't move $oldEventPath -> $newEventPath: $!" ); + } + + print( "Updating configuration.\n" ); + $sql = "update Config set Value = ? where Name = 'ZM_USE_DEEP_STORAGE'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute( 1 ) or die( "Can't execute: ".$sth->errstr() ); + + print( "All events converted.\n\n" ); + } + else + { + print( "Aborting event conversion.\n\n" ); + } +} +if ( $freshen ) +{ + print( "\nFreshening configuration in database\n" ); + loadConfigFromDB(); + saveConfigToDB(); +} +if ( $version ) +{ + my ( $detaint_version ) = $version =~ /^([\w.]+)$/; + $version = $detaint_version; + + if ( ZM_VERSION eq $version ) + { + print( "\nDatabase already at version $version, update aborted.\n\n" ); + exit( -1 ); + } + + print( "\nInitiating database upgrade to version ".ZM_VERSION." from version $version\n" ); + if ( $interactive ) + { + if ( ZM_DYN_DB_VERSION && ZM_DYN_DB_VERSION ne $version ) + { + print( "\nWARNING - You have specified an upgrade from version $version but the database version found is ".ZM_DYN_DB_VERSION.". Is this correct?\nPress enter to continue or ctrl-C to abort : " ); + my $response = ; + } + + print( "\nPlease ensure that ZoneMinder is stopped on your system prior to upgrading the database.\nPress enter to continue or ctrl-C to stop : " ); + my $response = ; + + print( "\nDo you wish to take a backup of your database prior to upgrading?\nThis may result in a large file in /tmp/zm if you have a lot of events.\nPress 'y' for a backup or 'n' to continue : " ); + $response = ; + chomp( $response ); + while ( $response !~ /^[yYnN]$/ ) + { + print( "Please press 'y' for a backup or 'n' to continue only : " ); + $response = ; + chomp( $response ); + } + + if ( $response =~ /^[yY]$/ ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + my $command = "mysqldump -h".$host; + $command .= " -P".$port if defined($port); + if ( $dbUser ) + { + $command .= " -u".$dbUser; + if ( $dbPass ) + { + $command .= " -p".$dbPass; + } + } + my $backup = "/tmp/zm/".ZM_DB_NAME."-".$version.".dump"; + $command .= " --add-drop-table --databases ".ZM_DB_NAME." > ".$backup; + print( "Creating backup to $backup. This may take several minutes.\n" ); + print( "Executing '$command'\n" ) if ( logDebugging() ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + print( "Output: $output\n" ); + } + if ( $status ) + { + die( "Command '$command' exited with status: $status\n" ); + } + else + { + print( "Database successfully backed up to $backup, proceeding to upgrade.\n" ); + } + } + elsif ( $response !~ /^[nN]$/ ) + { + die( "Unexpected response '$response'" ); + } + } + sub patchDB + { + my $dbh = shift; + my $version = shift; + + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + my $command = "mysql -h".$host; + $command .= " -P".$port if defined($port); + if ( $dbUser ) + { + $command .= " -u".$dbUser; + if ( $dbPass ) + { + $command .= " -p".$dbPass; + } + } + $command .= " ".ZM_DB_NAME." < "; + if ( $updateDir ) + { + $command .= $updateDir; + } + else + { + $command .= ZM_PATH_BUILD."/db"; + } + $command .= "/zm_update-".$version.".sql"; + + print( "Executing '$command'\n" ) if ( logDebugging() ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + print( "Output: $output\n" ); + } + if ( $status ) + { + die( "Command '$command' exited with status: $status\n" ); + } + else + { + print( "\nDatabase successfully upgraded from version $version.\n" ); + my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + print( "\nUpgrading database to version ".ZM_VERSION."\n" ); + + # Update config first of all + loadConfigFromDB(); + saveConfigToDB(); + + my $dbh = zmDbConnect(); + + my $cascade = undef; + if ( $cascade || $version eq "1.19.0" ) + { + # Patch the database + patchDB( $dbh, "1.19.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.1" ) + { + # Patch the database + patchDB( $dbh, "1.19.1"); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.2" ) + { + # Patch the database + patchDB( $dbh, "1.19.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.3" ) + { + # Patch the database + patchDB( $dbh, "1.19.3" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.4" ) + { + require DBI; + + # Rename the event directories and create a new symlink for the names + chdir( EVENT_PATH ); + + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( -d $monitor->{Name} ) + { + rename( $monitor->{Name}, $monitor->{Id} ) or warn( "Can't rename existing monitor directory '$monitor->{Name}' to '$monitor->{Id}': $!" ); + symlink( $monitor->{Id}, $monitor->{Name} ) or warn( "Can't symlink monitor directory '$monitor->{Id}' to '$monitor->{Name}': $!" ); + } + } + $sth->finish(); + + # Patch the database + patchDB( $dbh, "1.19.4" ); + + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.5" ) + { + print( "\nThis version now only uses one database user.\nPlease ensure you have run zmconfig.pl and re-entered your database username and password prior to upgrading, or the upgrade will fail.\nPress enter to continue or ctrl-C to stop : " ); + # Patch the database + my $dummy = ; + patchDB( $dbh, "1.19.5" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.20.0" ) + { + # Patch the database + patchDB( $dbh, "1.20.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.20.1" ) + { + # Patch the database + patchDB( $dbh, "1.20.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.0" ) + { + # Patch the database + patchDB( $dbh, "1.21.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.1" ) + { + # Patch the database + patchDB( $dbh, "1.21.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.2" ) + { + # Patch the database + patchDB( $dbh, "1.21.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.3" ) + { + # Patch the database + patchDB( $dbh, "1.21.3" ); + + # Add appropriate widths and heights to events + { + print( "Updating events. This may take a few minutes. Please wait.\n" ); + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + my $sql = "update Events set Width = ?, Height = ? where MonitorId = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $monitor->{Width}, $monitor->{Height}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + } + + # Add sequence numbers + { + print( "Updating monitor sequences. Please wait.\n" ); + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my $sequence = 1; + while( my $monitor = $sth->fetchrow_hashref() ) + { + my $sql = "update Monitors set Sequence = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $sequence++, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + } + + # Update saved filters + { + print( "Updating saved filters. Please wait.\n" ); + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @filters; + while( my $filter = $sth->fetchrow_hashref() ) + { + push( @filters, $filter ); + } + $sth->finish(); + $sql = "update Filters set Query = ? where Name = ?"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $filter ( @filters ) + { + if ( $filter->{Query} =~ /op\d=&/ ) + { + ( my $newQuery = $filter->{Query} ) =~ s/(op\d=)&/$1=&/g; + $res = $sth->execute( $newQuery, $filter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.4" ) + { + # Patch the database + patchDB( $dbh, "1.21.4" ); + + # Convert zones to new format + { + print( "Updating zones. Please wait.\n" ); + + # Get the existing zones from the DB + my $sql = "select Z.*,M.Width,M.Height from Zones as Z inner join Monitors as M on (Z.MonitorId = M.Id)"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @zones; + while( my $zone = $sth->fetchrow_hashref() ) + { + push( @zones, $zone ); + } + $sth->finish(); + + no strict 'refs'; + foreach my $zone ( @zones ) + { + # Create the coordinate strings + if ( $zone->{Units} eq "Pixels" ) + { + my $sql = "update Zones set NumCoords = 4, Coords = concat( LoX,',',LoY,' ',HiX,',',LoY,' ',HiX,',',HiY,' ',LoX,',',HiY ), Area = round( ((HiX-LoX)+1)*((HiY-LoY)+1) ) where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + else + { + my $loX = ($zone->{LoX} * ($zone->{Width}-1) ) / 100; + my $hiX = ($zone->{HiX} * ($zone->{Width}-1) ) / 100; + my $loY = ($zone->{LoY} * ($zone->{Height}-1) ) / 100; + my $hiY = ($zone->{HiY} * ($zone->{Height}-1) ) / 100; + my $area = (($hiX-$loX)+1)*(($hiY-$loY)+1); + my $sql = "update Zones set NumCoords = 4, Coords = concat( round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?) ), Area = round(?), MinAlarmPixels = round(?), MaxAlarmPixels = round(?), MinFilterPixels = round(?), MaxFilterPixels = round(?), MinBlobPixels = round(?), MaxBlobPixels = round(?) where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $loX, $loY, $hiX, $loY, $hiX, $hiY, $loX, $hiY, $area, ($zone->{MinAlarmPixels}*$area)/100, ($zone->{MaxAlarmPixels}*$area)/100, ($zone->{MinFilterPixels}*$area)/100, ($zone->{MaxFilterPixels}*$area)/100, ($zone->{MinBlobPixels}*$area)/100, ($zone->{MaxBlobPixels}*$area)/100, $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + # Convert run states to new format + { + print( "Updating run states. Please wait.\n" ); + + # Get the existing zones from the DB + my $sql = "select * from States"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @states; + while( my $state = $sth->fetchrow_hashref() ) + { + push( @states, $state ); + } + $sth->finish(); + + foreach my $state ( @states ) + { + my @new_defns; + foreach my $defn ( split( /,/, $state->{Definition} ) ) + { + push( @new_defns, $defn.":1" ); + } + my $sql = "update States set Definition = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( join( ',', @new_defns ), $state->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.0" ) + { + # Patch the database + patchDB( $dbh, "1.22.0" ); + + # Check for maximum FPS setting and update alarm max fps settings + { + print( "Updating monitors. Please wait.\n" ); + if ( defined(&ZM_NO_MAX_FPS_ON_ALARM) && &ZM_NO_MAX_FPS_ON_ALARM ) + { + # Update the individual monitor settings to match the previous global one + my $sql = "update Monitors set AlarmMaxFPS = NULL"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + else + { + # Update the individual monitor settings to match the previous global one + my $sql = "update Monitors set AlarmMaxFPS = MaxFPS"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + } + { + print( "Updating mail configuration. Please wait.\n" ); + my ( $sql, $sth, $res ); + if ( defined(&ZM_EMAIL_TEXT) && &ZM_EMAIL_TEXT ) + { + my ( $email_subject, $email_body ) = ZM_EMAIL_TEXT =~ /subject\s*=\s*"([^\n]*)".*body\s*=\s*"(.*)"?$/ms; + $sql = "replace into Config set Id = 0, Name = 'ZM_EMAIL_SUBJECT', Value = '".$email_subject."', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)', Hint = 'string', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The subject of the email used to send matching event details', Help = 'This option is used to define the subject of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + $sql = "replace into Config set Id = 0, Name = 'ZM_EMAIL_BODY', Value = '".$email_body."', Hint = 'free text', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The body of the email used to send matching event details', Help = 'This option is used to define the content of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + if ( defined(&ZM_MESSAGE_TEXT) && &ZM_MESSAGE_TEXT ) + { + my ( $message_subject, $message_body ) = ZM_MESSAGE_TEXT =~ /subject\s*=\s*"([^\n]*)".*body\s*=\s*"(.*)"?$/ms; + $sql = "replace into Config set Id = 0, Name = 'ZM_MESSAGE_SUBJECT', Value = '".$message_subject."', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI%', Hint = 'string', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The subject of the message used to send matching event details', Help = 'This option is used to define the subject of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + $sql = "replace into Config set Id = 0, Name = 'ZM_MESSAGE_BODY', Value = '".$message_body."', Type = 'text', DefaultValue = 'ZM alarm detected - %ED% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.', Hint = 'free text', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The body of the message used to send matching event details', Help = 'This option is used to define the content of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.1" ) + { + # Patch the database + patchDB( $dbh, "1.22.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.2" ) + { + # Patch the database + patchDB( $dbh, "1.22.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.3" ) + { + # Patch the database + patchDB( $dbh, "1.22.3" ); + + # Convert timestamp strings to new format + { + my $sql = "select * from Monitors"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @db_monitors; + while( my $db_monitor = $sth->fetchrow_hashref() ) + { + push( @db_monitors, $db_monitor ); + } + $sth->finish(); + foreach my $db_monitor ( @db_monitors ) + { + if ( $db_monitor->{LabelFormat} =~ /\%\%s/ ) + { + $db_monitor->{LabelFormat} =~ s/\%\%s/%N/; + $db_monitor->{LabelFormat} =~ s/\%\%s/%Q/; + + my $sql = "update Monitors set LabelFormat = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $db_monitor->{LabelFormat}, $db_monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + + # Convert filters to new format + { + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @dbFilters; + while( my $dbFilter = $sth->fetchrow_hashref() ) + { + push( @dbFilters, $dbFilter ); + } + $sth->finish(); + foreach my $dbFilter ( @dbFilters ) + { + my %filter_terms; + foreach my $filter_parm ( split( /&/, $dbFilter->{Query} ) ) + { + my( $key, $value ) = split( /=/, $filter_parm, 2 ); + if ( $key ) + { + $filter_terms{$key} = $value; + } + } + my $filter = { 'terms' => [] }; + for ( my $i = 1; $i <= $filter_terms{trms}; $i++ ) + { + my $term = {}; + my $conjunction_name = "cnj$i"; + my $obracket_name = "obr$i"; + my $cbracket_name = "cbr$i"; + my $attr_name = "attr$i"; + my $op_name = "op$i"; + my $value_name = "val$i"; + + $term->{cnj} = $filter_terms{$conjunction_name} if ( $filter_terms{$conjunction_name} ); + $term->{obr} = $filter_terms{$obracket_name} if ( $filter_terms{$obracket_name} ); + $term->{attr} = $filter_terms{$attr_name} if ( $filter_terms{$attr_name} ); + $term->{val} = $filter_terms{$value_name} if ( defined($filter_terms{$value_name}) ); + $term->{op} = $filter_terms{$op_name} if ( $filter_terms{$op_name} ); + $term->{cbr} = $filter_terms{$cbracket_name} if ( $filter_terms{$cbracket_name} ); + push( @{$filter->{terms}}, $term ); + } + $filter->{sort_field} = $filter_terms{sort_field} if ( $filter_terms{sort_field} ); + $filter->{sort_asc} = $filter_terms{sort_asc} if ( $filter_terms{sort_asc} ); + $filter->{limit} = $filter_terms{limit} if ( $filter_terms{limit} ); + + my $newQuery = 'a:'.int(keys(%$filter)).':{s:5:"terms";a:'.int(@{$filter->{terms}}).':{'; + my $i = 0; + foreach my $term ( @{$filter->{terms}} ) + { + $newQuery .= 'i:'.$i.';a:'.int(keys(%$term)).':{'; + while ( my ( $key, $val ) = each( %$term ) ) + { + $newQuery .= 's:'.length($key).':"'.$key.'";'; + $newQuery .= 's:'.length($val).':"'.$val.'";'; + } + $newQuery .= '}'; + $i++; + } + $newQuery .= '}'; + foreach my $field ( "sort_field", "sort_asc", "limit" ) + { + if ( defined($filter->{$field}) ) + { + $newQuery .= 's:'.length($field).':"'.$field.'";'; + $newQuery .= 's:'.length($filter->{$field}).':"'.$filter->{$field}.'";'; + } + } + $newQuery .= '}'; + + my $sql = "update Filters set Query = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $newQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + # Update the stream quality setting to the old image quality ones + { + my $dbh = zmDbConnect(); + + my $sql = "update Config set Value = ? where Name = 'ZM_JPEG_STREAM_QUALITY'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( ZM_JPEG_IMAGE_QUALITY ) or die( "Can't execute: ".$sth->errstr() ); + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.0" ) + { + # Patch the database + patchDB( $dbh, "1.23.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.1" ) + { + # Patch the database + patchDB( $dbh, "1.23.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.2" ) + { + # Patch the database + patchDB( $dbh, "1.23.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.3" ) + { + # Patch the database + patchDB( $dbh, "1.23.3" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.0" ) + { + # Patch the database + patchDB( $dbh, "1.24.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.1" ) + { + # Patch the database + patchDB( $dbh, "1.24.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.2" ) + { + # Patch the database + patchDB( $dbh, "1.24.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.3" ) + { + my $result = eval + { + require PHP::Serialization; + PHP::Serialization->import(); + }; + die( "Unable to perform upgrade from 1.24.3, PHP::Serialization module not found" ) if ( $result ); + + # Patch the database + patchDB( $dbh, "1.24.3" ); + + # Convert filters to JSON from PHP format serialisation + { + print( "\nConverting filters from PHP to JSON format\n" ); + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @dbFilters; + while( my $dbFilter = $sth->fetchrow_hashref() ) + { + push( @dbFilters, $dbFilter ); + } + $sth->finish(); + foreach my $dbFilter ( @dbFilters ) + { + print( " ".$dbFilter->{Name} ); + eval { + my $phpQuery = $dbFilter->{Query}; + my $query = PHP::Serialization::unserialize( $phpQuery ); + my $jsonQuery = jsonEncode( $query ); + my $sql = "update Filters set Query = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $jsonQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + }; + if ( $@ ) + { + print( " - failed, please check or report. Query is '".$dbFilter->{Query}."'\n" ); + print( $@ ); + } + else + { + print( " - complete\n" ); + } + } + print( "Conversion complete\n" ); + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.4" ) + { + # Patch the database + patchDB( $dbh, "1.24.4" ); + + # Copy the FTP specific values to the new general config + my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'"; + my $fetchSth = $dbh->prepare_cached( $fetchSql ) or die( "Can't prepare '$fetchSql': ".$dbh->errstr() ); + my $updateSql = "update Config set Value = ? where Name = ?"; + my $updateSth = $dbh->prepare_cached( $updateSql ) or die( "Can't prepare '$updateSql': ".$dbh->errstr() ); + my $fetchRes = $fetchSth->execute() or die( "Can't execute: ".$fetchSth->errstr() ); + while( my $config = $fetchSth->fetchrow_hashref() ) + { + ( my $name = $config->{Name} ) =~ s/_FTP_/_/; + my $updateRes = $updateSth->execute( $config->{Value}, $name ) or die( "Can't execute: ".$updateSth->errstr() ); + } + $cascade = !undef; + } + if ( $cascade ) + { + my $installed_version = ZM_VERSION; + my $sql = "update Config set Value = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( "$installed_version", "ZM_DYN_DB_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); + $res = $sth->execute( "$installed_version", "ZM_DYN_CURR_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); + $dbh->disconnect(); + } + else + { + $dbh->disconnect(); + die( "Can't find upgrade from version '$version'" ); + } + print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" ); +} +exit( 0 ); diff --git a/scripts/zmupdate.pl.in b/scripts/zmupdate.pl.in new file mode 100644 index 000000000..1a3d8fd58 --- /dev/null +++ b/scripts/zmupdate.pl.in @@ -0,0 +1,984 @@ +#!/usr/bin/perl -w +# +# ========================================================================== +# +# ZoneMinder Update Script, $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 script just checks what the most recent release of ZoneMinder is +# at the the moment. It will eventually be responsible for applying and +# configuring upgrades etc, including on the fly upgrades. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant CHECK_INTERVAL => (1*24*60*60); # Interval between version checks + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder::Base qw(:all); +use ZoneMinder::Config qw(:all); +use ZoneMinder::Logger qw(:all); +use ZoneMinder::General qw(:all); +use ZoneMinder::Database qw(:all); +use ZoneMinder::ConfigAdmin qw( :functions ); +use POSIX; +use DBI; +use Getopt::Long; +use Data::Dumper; + +use constant EVENT_PATH => (ZM_DIR_EVENTS=~m|/|)?ZM_DIR_EVENTS:(ZM_PATH_WEB.'/'.ZM_DIR_EVENTS); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin:/usr/local/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +my $web_uid = (getpwnam( ZM_WEB_USER ))[2]; +my $use_log = (($> == 0) || ($> == $web_uid)); + +logInit( toFile=>$use_log?DEBUG:NOLOG ); +logSetSignal(); + +my $interactive = 1; +my $check = 0; +my $freshen = 0; +my $rename = 0; +my $zoneFix = 0; +my $migrateEvents = 0; +my $version = ''; +my $dbUser = ZM_DB_USER; +my $dbPass = ZM_DB_PASS; +my $updateDir = ''; +sub Usage +{ + print( " +Usage: zmupdate.pl <-c,--check|-f,--freshen|-v,--version=> [-u -p]> +Parameters are :- +-c, --check - Check for updated versions of ZoneMinder +-f, --freshen - Freshen the configuration in the database. Equivalent of old zmconfig.pl -noi +-v, --version= - Force upgrade to the current version from +-u, --user= - Alternate DB user with privileges to alter DB +-p, --pass= - Password of alternate DB user with privileges to alter DB +-d,--dir= - Directory containing update files if not in default build location +"); + exit( -1 ); +} + +if ( !GetOptions( 'check'=>\$check, 'freshen'=>\$freshen, 'rename'=>\$rename, 'zone-fix'=>\$zoneFix, 'migrate-events'=>\$migrateEvents, 'version=s'=>\$version, 'interactive!'=>\$interactive, 'user:s'=>\$dbUser, 'pass:s'=>\$dbPass, 'dir:s'=>\$updateDir ) ) +{ + Usage(); +} + +if ( ! ($check || $freshen || $rename || $zoneFix || $migrateEvents || $version) ) +{ + if ( ZM_DYN_DB_VERSION ) + { + $version = ZM_DYN_DB_VERSION; + } + else + { + print( STDERR "Please give a valid option\n" ); + Usage(); + } +} + +if ( ($check + $freshen + $rename + $zoneFix + $migrateEvents + ($version?1:0)) > 1 ) +{ + print( STDERR "Please give only one option\n" ); + Usage(); +} + +if ( $check && ZM_CHECK_FOR_UPDATES ) +{ + print( "Update agent starting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); + + my $dbh = zmDbConnect(); + + my $currVersion = ZM_DYN_CURR_VERSION; + my $lastVersion = ZM_DYN_LAST_VERSION; + my $lastCheck = ZM_DYN_LAST_CHECK; + + if ( !$currVersion ) + { + $currVersion = ZM_VERSION; + + my $sql = "update Config set Value = ? where Name = 'ZM_DYN_CURR_VERSION'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( "$currVersion" ) or die( "Can't execute: ".$sth->errstr() ); + } + zmDbDisconnect(); + + while( 1 ) + { + my $now = time(); + if ( !$lastVersion || !$lastCheck || (($now-$lastCheck) > CHECK_INTERVAL) ) + { + $dbh = zmDbConnect(); + + Info( "Checking for updates\n" ); + + use LWP::UserAgent; + my $ua = LWP::UserAgent->new; + $ua->agent( "ZoneMinder Update Agent/".ZM_VERSION ); + if ( eval('defined(ZM_UPDATE_CHECK_PROXY)') ) + { + no strict 'subs'; + if ( ZM_UPDATE_CHECK_PROXY ) + { + $ua->proxy( "http", ZM_UPDATE_CHECK_PROXY ); + } + use strict 'subs'; + } + my $req = HTTP::Request->new( GET=>'http://www.zoneminder.com/version' ); + my $res = $ua->request($req); + + if ( $res->is_success ) + { + $lastVersion = $res->content; + chomp($lastVersion); + $lastCheck = $now; + + Info( "Got version: '".$lastVersion."'\n" ); + + my $lv_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_VERSION'"; + my $lv_sth = $dbh->prepare_cached( $lv_sql ) or die( "Can't prepare '$lv_sql': ".$dbh->errstr() ); + my $lv_res = $lv_sth->execute( $lastVersion ) or die( "Can't execute: ".$lv_sth->errstr() ); + + my $lc_sql = "update Config set Value = ? where Name = 'ZM_DYN_LAST_CHECK'"; + my $lc_sth = $dbh->prepare_cached( $lc_sql ) or die( "Can't prepare '$lc_sql': ".$dbh->errstr() ); + my $lc_res = $lc_sth->execute( $lastCheck ) or die( "Can't execute: ".$lc_sth->errstr() ); + } + else + { + Error( "Error check failed: '".$res->status_line()."'\n" ); + } + zmDbDisconnect(); + } + sleep( 3600 ); + } + print( "Update agent exiting at ".strftime( '%y/%m/%d %H:%M:%S', localtime() )."\n" ); +} +if ( $rename ) +{ + require File::Find; + + chdir( EVENT_PATH ); + + sub renameImage + { + my $file = $_; + + # Ignore directories + if ( -d $file ) + { + print( "Checking directory '$file'\n" ); + return; + } + if ( $file !~ /(capture|analyse)-(\d+)(\.jpg)/ ) + { + return; + } + my $newFile = "$2-$1$3"; + + print( "Renaming '$file' to '$newFile'\n" ); + rename( $file, $newFile ) or warn( "Can't rename '$file' to '$newFile'" ); + } + + File::Find::find( \&renameImage, '.' ); +} +if ( $zoneFix ) +{ + require DBI; + + my $dbh = zmDbConnect(); + + my $sql = "select Z.*, M.Width as MonitorWidth, M.Height as MonitorHeight from Zones as Z inner join Monitors as M on Z.MonitorId = M.Id where Z.Units = 'Percent'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @zones; + while( my $zone = $sth->fetchrow_hashref() ) + { + push( @zones, $zone ); + } + $sth->finish(); + + foreach my $zone ( @zones ) + { + my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100; + my $zone_height = (($zone->{HiY}*$zone->{MonitorHeight})-($zone->{LoY}*$zone->{MonitorHeight}))/100; + my $zone_area = $zone_width * $zone_height; + my $monitor_area = $zone->{MonitorWidth} * $zone->{MonitorHeight}; + my $sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( + ($zone->{MinAlarmPixels}*$monitor_area)/$zone_area, + ($zone->{MaxAlarmPixels}*$monitor_area)/$zone_area, + ($zone->{MinFilterPixels}*$monitor_area)/$zone_area, + ($zone->{MaxFilterPixels}*$monitor_area)/$zone_area, + ($zone->{MinBlobPixels}*$monitor_area)/$zone_area, + ($zone->{MaxBlobPixels}*$monitor_area)/$zone_area, + $zone->{Id} + ) or die( "Can't execute: ".$sth->errstr() ); + } +} +if ( $migrateEvents ) +{ + my $webUid = (getpwnam( ZM_WEB_USER ))[2]; + my $webGid = (getgrnam( ZM_WEB_USER ))[2]; + + if ( !(($> == 0) || ($> == $webUid)) ) + { + print( "Error, migrating events can only be done as user root or ".ZM_WEB_USER.".\n" ); + exit( -1 ); + } + + # Run as web user/group + $( = $webGid; + $) = $webGid; + $< = $webUid; + $> = $webUid; + + print( "\nAbout to convert saved events to deep storage, please ensure that ZoneMinder is fully stopped before proceeding.\nThis process is not easily reversible. Are you sure you wish to proceed?\n\nPress 'y' to continue or 'n' to abort : " ); + my $response = ; + chomp( $response ); + while ( $response !~ /^[yYnN]$/ ) + { + print( "Please press 'y' to continue or 'n' to abort only : " ); + $response = ; + chomp( $response ); + } + + if ( $response =~ /^[yY]$/ ) + { + print( "Converting all events to deep storage.\n" ); + + chdir( ZM_PATH_WEB ); + my $dbh = zmDbConnect(); + my $sql = "select *, unix_timestamp(StartTime) as UnixStartTime from Events"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute(); + if ( !$res ) + { + Fatal( "Can't fetch Events: ".$sth->errstr() ); + } + + while( my $event = $sth->fetchrow_hashref() ) + { + my $oldEventPath = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.$event->{Id}; + + if ( !-d $oldEventPath ) + { + print( "Warning, can't find old event path '$oldEventPath', already converted?\n" ); + next; + } + + print( "Converting event ".$event->{Id}."\n" ); + my $newDatePath = ZM_DIR_EVENTS.'/'.$event->{MonitorId}.'/'.strftime( "%y/%m/%d", localtime($event->{UnixStartTime}) ); + my $newTimePath = strftime( "%H/%M/%S", localtime($event->{UnixStartTime}) ); + my $newEventPath = $newDatePath.'/'.$newTimePath; + ( my $truncEventPath = $newEventPath ) =~ s|/\d+$||; + makePath( $truncEventPath, ZM_PATH_WEB ); + my $idLink = $newDatePath.'/.'.$event->{Id}; + symlink( $newTimePath, $idLink ) or die( "Can't symlink $newTimePath -> $idLink: $!" ); + rename( $oldEventPath, $newEventPath ) or die( "Can't move $oldEventPath -> $newEventPath: $!" ); + } + + print( "Updating configuration.\n" ); + $sql = "update Config set Value = ? where Name = 'ZM_USE_DEEP_STORAGE'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute( 1 ) or die( "Can't execute: ".$sth->errstr() ); + + print( "All events converted.\n\n" ); + } + else + { + print( "Aborting event conversion.\n\n" ); + } +} +if ( $freshen ) +{ + print( "\nFreshening configuration in database\n" ); + loadConfigFromDB(); + saveConfigToDB(); +} +if ( $version ) +{ + my ( $detaint_version ) = $version =~ /^([\w.]+)$/; + $version = $detaint_version; + + if ( ZM_VERSION eq $version ) + { + print( "\nDatabase already at version $version, update aborted.\n\n" ); + exit( -1 ); + } + + print( "\nInitiating database upgrade to version ".ZM_VERSION." from version $version\n" ); + if ( $interactive ) + { + if ( ZM_DYN_DB_VERSION && ZM_DYN_DB_VERSION ne $version ) + { + print( "\nWARNING - You have specified an upgrade from version $version but the database version found is ".ZM_DYN_DB_VERSION.". Is this correct?\nPress enter to continue or ctrl-C to abort : " ); + my $response = ; + } + + print( "\nPlease ensure that ZoneMinder is stopped on your system prior to upgrading the database.\nPress enter to continue or ctrl-C to stop : " ); + my $response = ; + + print( "\nDo you wish to take a backup of your database prior to upgrading?\nThis may result in a large file in @ZM_TMPDIR@ if you have a lot of events.\nPress 'y' for a backup or 'n' to continue : " ); + $response = ; + chomp( $response ); + while ( $response !~ /^[yYnN]$/ ) + { + print( "Please press 'y' for a backup or 'n' to continue only : " ); + $response = ; + chomp( $response ); + } + + if ( $response =~ /^[yY]$/ ) + { + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + my $command = "mysqldump -h".$host; + $command .= " -P".$port if defined($port); + if ( $dbUser ) + { + $command .= " -u".$dbUser; + if ( $dbPass ) + { + $command .= " -p".$dbPass; + } + } + my $backup = "@ZM_TMPDIR@/".ZM_DB_NAME."-".$version.".dump"; + $command .= " --add-drop-table --databases ".ZM_DB_NAME." > ".$backup; + print( "Creating backup to $backup. This may take several minutes.\n" ); + print( "Executing '$command'\n" ) if ( logDebugging() ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + print( "Output: $output\n" ); + } + if ( $status ) + { + die( "Command '$command' exited with status: $status\n" ); + } + else + { + print( "Database successfully backed up to $backup, proceeding to upgrade.\n" ); + } + } + elsif ( $response !~ /^[nN]$/ ) + { + die( "Unexpected response '$response'" ); + } + } + sub patchDB + { + my $dbh = shift; + my $version = shift; + + my ( $host, $port ) = ( ZM_DB_HOST =~ /^([^:]+)(?::(.+))?$/ ); + my $command = "mysql -h".$host; + $command .= " -P".$port if defined($port); + if ( $dbUser ) + { + $command .= " -u".$dbUser; + if ( $dbPass ) + { + $command .= " -p".$dbPass; + } + } + $command .= " ".ZM_DB_NAME." < "; + if ( $updateDir ) + { + $command .= $updateDir; + } + else + { + $command .= ZM_PATH_BUILD."/db"; + } + $command .= "/zm_update-".$version.".sql"; + + print( "Executing '$command'\n" ) if ( logDebugging() ); + my $output = qx($command); + my $status = $? >> 8; + if ( $status || logDebugging() ) + { + chomp( $output ); + print( "Output: $output\n" ); + } + if ( $status ) + { + die( "Command '$command' exited with status: $status\n" ); + } + else + { + print( "\nDatabase successfully upgraded from version $version.\n" ); + my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + print( "\nUpgrading database to version ".ZM_VERSION."\n" ); + + # Update config first of all + loadConfigFromDB(); + saveConfigToDB(); + + my $dbh = zmDbConnect(); + + my $cascade = undef; + if ( $cascade || $version eq "1.19.0" ) + { + # Patch the database + patchDB( $dbh, "1.19.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.1" ) + { + # Patch the database + patchDB( $dbh, "1.19.1"); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.2" ) + { + # Patch the database + patchDB( $dbh, "1.19.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.3" ) + { + # Patch the database + patchDB( $dbh, "1.19.3" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.4" ) + { + require DBI; + + # Rename the event directories and create a new symlink for the names + chdir( EVENT_PATH ); + + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( -d $monitor->{Name} ) + { + rename( $monitor->{Name}, $monitor->{Id} ) or warn( "Can't rename existing monitor directory '$monitor->{Name}' to '$monitor->{Id}': $!" ); + symlink( $monitor->{Id}, $monitor->{Name} ) or warn( "Can't symlink monitor directory '$monitor->{Id}' to '$monitor->{Name}': $!" ); + } + } + $sth->finish(); + + # Patch the database + patchDB( $dbh, "1.19.4" ); + + $cascade = !undef; + } + if ( $cascade || $version eq "1.19.5" ) + { + print( "\nThis version now only uses one database user.\nPlease ensure you have run zmconfig.pl and re-entered your database username and password prior to upgrading, or the upgrade will fail.\nPress enter to continue or ctrl-C to stop : " ); + # Patch the database + my $dummy = ; + patchDB( $dbh, "1.19.5" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.20.0" ) + { + # Patch the database + patchDB( $dbh, "1.20.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.20.1" ) + { + # Patch the database + patchDB( $dbh, "1.20.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.0" ) + { + # Patch the database + patchDB( $dbh, "1.21.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.1" ) + { + # Patch the database + patchDB( $dbh, "1.21.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.2" ) + { + # Patch the database + patchDB( $dbh, "1.21.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.3" ) + { + # Patch the database + patchDB( $dbh, "1.21.3" ); + + # Add appropriate widths and heights to events + { + print( "Updating events. This may take a few minutes. Please wait.\n" ); + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + my $sql = "update Events set Width = ?, Height = ? where MonitorId = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $monitor->{Width}, $monitor->{Height}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + } + + # Add sequence numbers + { + print( "Updating monitor sequences. Please wait.\n" ); + my $sql = "select * from Monitors order by Id"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my $sequence = 1; + while( my $monitor = $sth->fetchrow_hashref() ) + { + my $sql = "update Monitors set Sequence = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $sequence++, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + $sth->finish(); + } + + # Update saved filters + { + print( "Updating saved filters. Please wait.\n" ); + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @filters; + while( my $filter = $sth->fetchrow_hashref() ) + { + push( @filters, $filter ); + } + $sth->finish(); + $sql = "update Filters set Query = ? where Name = ?"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + foreach my $filter ( @filters ) + { + if ( $filter->{Query} =~ /op\d=&/ ) + { + ( my $newQuery = $filter->{Query} ) =~ s/(op\d=)&/$1=&/g; + $res = $sth->execute( $newQuery, $filter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + + $cascade = !undef; + } + if ( $cascade || $version eq "1.21.4" ) + { + # Patch the database + patchDB( $dbh, "1.21.4" ); + + # Convert zones to new format + { + print( "Updating zones. Please wait.\n" ); + + # Get the existing zones from the DB + my $sql = "select Z.*,M.Width,M.Height from Zones as Z inner join Monitors as M on (Z.MonitorId = M.Id)"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @zones; + while( my $zone = $sth->fetchrow_hashref() ) + { + push( @zones, $zone ); + } + $sth->finish(); + + no strict 'refs'; + foreach my $zone ( @zones ) + { + # Create the coordinate strings + if ( $zone->{Units} eq "Pixels" ) + { + my $sql = "update Zones set NumCoords = 4, Coords = concat( LoX,',',LoY,' ',HiX,',',LoY,' ',HiX,',',HiY,' ',LoX,',',HiY ), Area = round( ((HiX-LoX)+1)*((HiY-LoY)+1) ) where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + else + { + my $loX = ($zone->{LoX} * ($zone->{Width}-1) ) / 100; + my $hiX = ($zone->{HiX} * ($zone->{Width}-1) ) / 100; + my $loY = ($zone->{LoY} * ($zone->{Height}-1) ) / 100; + my $hiY = ($zone->{HiY} * ($zone->{Height}-1) ) / 100; + my $area = (($hiX-$loX)+1)*(($hiY-$loY)+1); + my $sql = "update Zones set NumCoords = 4, Coords = concat( round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?),' ',round(?),',',round(?) ), Area = round(?), MinAlarmPixels = round(?), MaxAlarmPixels = round(?), MinFilterPixels = round(?), MaxFilterPixels = round(?), MinBlobPixels = round(?), MaxBlobPixels = round(?) where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $loX, $loY, $hiX, $loY, $hiX, $hiY, $loX, $hiY, $area, ($zone->{MinAlarmPixels}*$area)/100, ($zone->{MaxAlarmPixels}*$area)/100, ($zone->{MinFilterPixels}*$area)/100, ($zone->{MaxFilterPixels}*$area)/100, ($zone->{MinBlobPixels}*$area)/100, ($zone->{MaxBlobPixels}*$area)/100, $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + # Convert run states to new format + { + print( "Updating run states. Please wait.\n" ); + + # Get the existing zones from the DB + my $sql = "select * from States"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @states; + while( my $state = $sth->fetchrow_hashref() ) + { + push( @states, $state ); + } + $sth->finish(); + + foreach my $state ( @states ) + { + my @new_defns; + foreach my $defn ( split( /,/, $state->{Definition} ) ) + { + push( @new_defns, $defn.":1" ); + } + my $sql = "update States set Definition = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( join( ',', @new_defns ), $state->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.0" ) + { + # Patch the database + patchDB( $dbh, "1.22.0" ); + + # Check for maximum FPS setting and update alarm max fps settings + { + print( "Updating monitors. Please wait.\n" ); + if ( defined(&ZM_NO_MAX_FPS_ON_ALARM) && &ZM_NO_MAX_FPS_ON_ALARM ) + { + # Update the individual monitor settings to match the previous global one + my $sql = "update Monitors set AlarmMaxFPS = NULL"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + else + { + # Update the individual monitor settings to match the previous global one + my $sql = "update Monitors set AlarmMaxFPS = MaxFPS"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + } + { + print( "Updating mail configuration. Please wait.\n" ); + my ( $sql, $sth, $res ); + if ( defined(&ZM_EMAIL_TEXT) && &ZM_EMAIL_TEXT ) + { + my ( $email_subject, $email_body ) = ZM_EMAIL_TEXT =~ /subject\s*=\s*"([^\n]*)".*body\s*=\s*"(.*)"?$/ms; + $sql = "replace into Config set Id = 0, Name = 'ZM_EMAIL_SUBJECT', Value = '".$email_subject."', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)', Hint = 'string', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The subject of the email used to send matching event details', Help = 'This option is used to define the subject of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + $sql = "replace into Config set Id = 0, Name = 'ZM_EMAIL_BODY', Value = '".$email_body."', Hint = 'free text', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The body of the email used to send matching event details', Help = 'This option is used to define the content of the email that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_EMAIL=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + if ( defined(&ZM_MESSAGE_TEXT) && &ZM_MESSAGE_TEXT ) + { + my ( $message_subject, $message_body ) = ZM_MESSAGE_TEXT =~ /subject\s*=\s*"([^\n]*)".*body\s*=\s*"(.*)"?$/ms; + $sql = "replace into Config set Id = 0, Name = 'ZM_MESSAGE_SUBJECT', Value = '".$message_subject."', Type = 'string', DefaultValue = 'ZoneMinder: Alarm - %MN%-%EI%', Hint = 'string', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The subject of the message used to send matching event details', Help = 'This option is used to define the subject of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + $sql = "replace into Config set Id = 0, Name = 'ZM_MESSAGE_BODY', Value = '".$message_body."', Type = 'text', DefaultValue = 'ZM alarm detected - %ED% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score.', Hint = 'free text', Pattern = '(?-xism:^(.+)\$)', Format = ' \$1 ', Prompt = 'The body of the message used to send matching event details', Help = 'This option is used to define the content of the message that is sent for any events that match the appropriate filters.', Category = 'mail', Readonly = '0', Requires = 'ZM_OPT_MESSAGE=1'"; + $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + } + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.1" ) + { + # Patch the database + patchDB( $dbh, "1.22.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.2" ) + { + # Patch the database + patchDB( $dbh, "1.22.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.22.3" ) + { + # Patch the database + patchDB( $dbh, "1.22.3" ); + + # Convert timestamp strings to new format + { + my $sql = "select * from Monitors"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @db_monitors; + while( my $db_monitor = $sth->fetchrow_hashref() ) + { + push( @db_monitors, $db_monitor ); + } + $sth->finish(); + foreach my $db_monitor ( @db_monitors ) + { + if ( $db_monitor->{LabelFormat} =~ /\%\%s/ ) + { + $db_monitor->{LabelFormat} =~ s/\%\%s/%N/; + $db_monitor->{LabelFormat} =~ s/\%\%s/%Q/; + + my $sql = "update Monitors set LabelFormat = ? where Id = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $db_monitor->{LabelFormat}, $db_monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + } + + # Convert filters to new format + { + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @dbFilters; + while( my $dbFilter = $sth->fetchrow_hashref() ) + { + push( @dbFilters, $dbFilter ); + } + $sth->finish(); + foreach my $dbFilter ( @dbFilters ) + { + my %filter_terms; + foreach my $filter_parm ( split( /&/, $dbFilter->{Query} ) ) + { + my( $key, $value ) = split( /=/, $filter_parm, 2 ); + if ( $key ) + { + $filter_terms{$key} = $value; + } + } + my $filter = { 'terms' => [] }; + for ( my $i = 1; $i <= $filter_terms{trms}; $i++ ) + { + my $term = {}; + my $conjunction_name = "cnj$i"; + my $obracket_name = "obr$i"; + my $cbracket_name = "cbr$i"; + my $attr_name = "attr$i"; + my $op_name = "op$i"; + my $value_name = "val$i"; + + $term->{cnj} = $filter_terms{$conjunction_name} if ( $filter_terms{$conjunction_name} ); + $term->{obr} = $filter_terms{$obracket_name} if ( $filter_terms{$obracket_name} ); + $term->{attr} = $filter_terms{$attr_name} if ( $filter_terms{$attr_name} ); + $term->{val} = $filter_terms{$value_name} if ( defined($filter_terms{$value_name}) ); + $term->{op} = $filter_terms{$op_name} if ( $filter_terms{$op_name} ); + $term->{cbr} = $filter_terms{$cbracket_name} if ( $filter_terms{$cbracket_name} ); + push( @{$filter->{terms}}, $term ); + } + $filter->{sort_field} = $filter_terms{sort_field} if ( $filter_terms{sort_field} ); + $filter->{sort_asc} = $filter_terms{sort_asc} if ( $filter_terms{sort_asc} ); + $filter->{limit} = $filter_terms{limit} if ( $filter_terms{limit} ); + + my $newQuery = 'a:'.int(keys(%$filter)).':{s:5:"terms";a:'.int(@{$filter->{terms}}).':{'; + my $i = 0; + foreach my $term ( @{$filter->{terms}} ) + { + $newQuery .= 'i:'.$i.';a:'.int(keys(%$term)).':{'; + while ( my ( $key, $val ) = each( %$term ) ) + { + $newQuery .= 's:'.length($key).':"'.$key.'";'; + $newQuery .= 's:'.length($val).':"'.$val.'";'; + } + $newQuery .= '}'; + $i++; + } + $newQuery .= '}'; + foreach my $field ( "sort_field", "sort_asc", "limit" ) + { + if ( defined($filter->{$field}) ) + { + $newQuery .= 's:'.length($field).':"'.$field.'";'; + $newQuery .= 's:'.length($filter->{$field}).':"'.$filter->{$field}.'";'; + } + } + $newQuery .= '}'; + + my $sql = "update Filters set Query = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $newQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + } + } + + # Update the stream quality setting to the old image quality ones + { + my $dbh = zmDbConnect(); + + my $sql = "update Config set Value = ? where Name = 'ZM_JPEG_STREAM_QUALITY'"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( ZM_JPEG_IMAGE_QUALITY ) or die( "Can't execute: ".$sth->errstr() ); + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.0" ) + { + # Patch the database + patchDB( $dbh, "1.23.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.1" ) + { + # Patch the database + patchDB( $dbh, "1.23.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.2" ) + { + # Patch the database + patchDB( $dbh, "1.23.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.23.3" ) + { + # Patch the database + patchDB( $dbh, "1.23.3" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.0" ) + { + # Patch the database + patchDB( $dbh, "1.24.0" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.1" ) + { + # Patch the database + patchDB( $dbh, "1.24.1" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.2" ) + { + # Patch the database + patchDB( $dbh, "1.24.2" ); + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.3" ) + { + my $result = eval + { + require PHP::Serialization; + PHP::Serialization->import(); + }; + die( "Unable to perform upgrade from 1.24.3, PHP::Serialization module not found" ) if ( $result ); + + # Patch the database + patchDB( $dbh, "1.24.3" ); + + # Convert filters to JSON from PHP format serialisation + { + print( "\nConverting filters from PHP to JSON format\n" ); + my $sql = "select * from Filters"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); + my @dbFilters; + while( my $dbFilter = $sth->fetchrow_hashref() ) + { + push( @dbFilters, $dbFilter ); + } + $sth->finish(); + foreach my $dbFilter ( @dbFilters ) + { + print( " ".$dbFilter->{Name} ); + eval { + my $phpQuery = $dbFilter->{Query}; + my $query = PHP::Serialization::unserialize( $phpQuery ); + my $jsonQuery = jsonEncode( $query ); + my $sql = "update Filters set Query = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( $jsonQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); + }; + if ( $@ ) + { + print( " - failed, please check or report. Query is '".$dbFilter->{Query}."'\n" ); + print( $@ ); + } + else + { + print( " - complete\n" ); + } + } + print( "Conversion complete\n" ); + } + $cascade = !undef; + } + if ( $cascade || $version eq "1.24.4" ) + { + # Patch the database + patchDB( $dbh, "1.24.4" ); + + # Copy the FTP specific values to the new general config + my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'"; + my $fetchSth = $dbh->prepare_cached( $fetchSql ) or die( "Can't prepare '$fetchSql': ".$dbh->errstr() ); + my $updateSql = "update Config set Value = ? where Name = ?"; + my $updateSth = $dbh->prepare_cached( $updateSql ) or die( "Can't prepare '$updateSql': ".$dbh->errstr() ); + my $fetchRes = $fetchSth->execute() or die( "Can't execute: ".$fetchSth->errstr() ); + while( my $config = $fetchSth->fetchrow_hashref() ) + { + ( my $name = $config->{Name} ) =~ s/_FTP_/_/; + my $updateRes = $updateSth->execute( $config->{Value}, $name ) or die( "Can't execute: ".$updateSth->errstr() ); + } + $cascade = !undef; + } + if ( $cascade ) + { + my $installed_version = ZM_VERSION; + my $sql = "update Config set Value = ? where Name = ?"; + my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute( "$installed_version", "ZM_DYN_DB_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); + $res = $sth->execute( "$installed_version", "ZM_DYN_CURR_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); + $dbh->disconnect(); + } + else + { + $dbh->disconnect(); + die( "Can't find upgrade from version '$version'" ); + } + print( "\nDatabase upgrade to version ".ZM_VERSION." successful.\n\n" ); +} +exit( 0 ); diff --git a/scripts/zmvideo.pl b/scripts/zmvideo.pl new file mode 100644 index 000000000..cd011d8b7 --- /dev/null +++ b/scripts/zmvideo.pl @@ -0,0 +1,243 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Video Creation Script, $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 script is used to create MPEG videos of events for the web pages +# or as email attachments. +# +use strict; +use bytes; + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use DBI; +use Data::Dumper; +use POSIX qw(strftime); +use Getopt::Long qw(:config no_ignore_case ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); + +my $event_id; +my $format = 'mpg'; +my $rate = ''; +my $scale = ''; +my $fps = ''; +my $size = ''; +my $overwrite = 0; + +my @formats = split( /\s+/, ZM_FFMPEG_FORMATS ); +for ( my $i = 0; $i < @formats; $i++ ) +{ + if ( $i =~ /^(.+)\*$/ ) + { + $format = $formats[$i] = $1; + } +} + +sub Usage +{ + print( " +Usage: zmvideo.pl -e ,--event= [--format ] [--rate=] [--scale=] [--fps=] [--size=] [--overwrite] +Parameters are :- +-e, --event= - What event to create the video for +-f, --format= - What format to create the video in, default is mpg. For ffmpeg only. +-r, --rate= - Relative rate , 1 = realtime, 2 = double speed , 0.5 = half speed etc +-s, --scale= - Scale, 1 = normal, 2 = double size, 0.5 = half size etc +-F, --fps= - Absolute frame rate, in frames per second +-S, --size= - Absolute video size, WxH or other specification supported by ffmpeg +-o, --overwrite - Whether to overwrite an existing file, off by default. +"); + exit( -1 ); +} + +if ( !GetOptions( 'event=i'=>\$event_id, 'format|f=s'=>\$format, 'rate|r=f'=>\$rate, 'scale|s=f'=>\$scale, 'fps|F=f'=>\$fps, 'size|S=s'=>\$size, 'overwrite'=>\$overwrite ) ) +{ + Usage(); +} + +if ( !$event_id || $event_id < 0 ) +{ + print( STDERR "Please give a valid event id\n" ); + Usage(); +} + +if ( !ZM_OPT_FFMPEG ) +{ + print( STDERR "Mpeg encoding is not currently enabled\n" ); + exit(-1); +} + +if ( !$rate && !$fps ) +{ + $rate = 1; +} + +if ( !$scale && !$size ) +{ + $scale = 1; +} + +if ( $rate && ($rate < 0.25 || $rate > 100) ) +{ + print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" ); + Usage(); +} + +if ( $scale && ($scale < 0.25 || $scale > 4) ) +{ + print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" ); + Usage(); +} + +if ( $fps && ($fps > 30) ) +{ + print( STDERR "FPS is out of range, <= 30\n" ); + Usage(); +} + +my ( $detaint_format ) = $format =~ /^(\w+)$/; +my ( $detaint_rate ) = $rate =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_scale ) = $scale =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_fps ) = $fps =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_size ) = $size =~ /^(\w+)$/; + +$format = $detaint_format; +$rate = $detaint_rate; +$scale = $detaint_scale; +$fps = $detaint_fps; +$size = $detaint_size; + +my $dbh = zmDbConnect(); + +my @filters; +my $sql = "select max(F.Delta)-min(F.Delta) as FullLength, E.*, unix_timestamp(E.StartTime) as Time, M.Name as MonitorName, M.Width as MonitorWidth, M.Height as MonitorHeight, M.Palette from Frames as F inner join Events as E on F.EventId = E.Id inner join Monitors as M on E.MonitorId = M.Id where EventId = '$event_id' group by F.EventId"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); +my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); +my $event = $sth->fetchrow_hashref(); +$sth->finish(); +my $event_path = getEventPath( $event ); +chdir( $event_path ); +( my $video_name = $event->{Name} ) =~ s/\s/_/g; + +my @file_parts; +if ( $rate ) +{ + my $file_rate = $rate; + $file_rate =~ s/\./_/; + $file_rate =~ s/_00//; + $file_rate =~ s/(_\d+)0+$/$1/; + $file_rate = 'r'.$file_rate; + push( @file_parts, $file_rate ); +} +elsif ( $fps ) +{ + my $file_fps = $fps; + $file_fps =~ s/\./_/; + $file_fps =~ s/_00//; + $file_fps =~ s/(_\d+)0+$/$1/; + $file_fps = 'R'.$file_fps; + push( @file_parts, $file_fps ); +} + +if ( $scale ) +{ + my $file_scale = $scale; + $file_scale =~ s/\./_/; + $file_scale =~ s/_00//; + $file_scale =~ s/(_\d+)0+$/$1/; + $file_scale = 's'.$file_scale; + push( @file_parts, $file_scale ); +} +elsif ( $size ) +{ + my $file_size = 'S'.$size; + push( @file_parts, $file_size ); +} +my $video_file = "$video_name-".$file_parts[0]."-".$file_parts[1].".$format"; + +if ( $overwrite || !-s $video_file ) +{ + Info( "Creating video file $video_file for event $event->{Id}\n" ); + + my $frame_rate = sprintf( "%.2f", $event->{Frames}/$event->{FullLength} ); + if ( $rate ) + { + if ( $rate != 1.0 ) + { + $frame_rate *= $rate; + } + } + elsif ( $fps ) + { + $frame_rate = $fps; + } + + my $width = $event->{MonitorWidth}; + my $height = $event->{MonitorHeight}; + my $video_size = " ${width}x${height}"; + + if ( $scale ) + { + if ( $scale != 1.0 ) + { + $width = int($width*$scale); + $height = int($height*$scale); + $video_size = " ${width}x${height}"; + } + } + elsif ( $size ) + { + $video_size = $size; + } + + my $command = ZM_PATH_FFMPEG." -y -r $frame_rate ".ZM_FFMPEG_INPUT_OPTIONS." -i %0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg -s $video_size ".ZM_FFMPEG_OUTPUT_OPTIONS." '$video_file' > ffmpeg.log 2>&1"; + Debug( $command."\n" ); + my $output = qx($command); + + my $status = $? >> 8; + if ( $status ) + { + Error( "Unable to generate video, check ".$event_path."/ffmpeg.log for details" ); + exit( -1 ); + } + + Info( "Finished $video_file\n" ); +} +else +{ + Info( "Video file $video_file already exists for event $event->{Id}\n" ); +} +#print( STDOUT $event->{MonitorId}.'/'.$event->{Id}.'/'.$video_file."\n" ); +print( STDOUT $video_file."\n" ); +exit( 0 ); diff --git a/scripts/zmvideo.pl.in b/scripts/zmvideo.pl.in new file mode 100644 index 000000000..236e5d20c --- /dev/null +++ b/scripts/zmvideo.pl.in @@ -0,0 +1,243 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder Video Creation Script, $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 script is used to create MPEG videos of events for the web pages +# or as email attachments. +# +use strict; +use bytes; + +# ========================================================================== +# +# You shouldn't need to change anything from here downwards +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use DBI; +use Data::Dumper; +use POSIX qw(strftime); +use Getopt::Long qw(:config no_ignore_case ); + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +logInit(); + +my $event_id; +my $format = 'mpg'; +my $rate = ''; +my $scale = ''; +my $fps = ''; +my $size = ''; +my $overwrite = 0; + +my @formats = split( /\s+/, ZM_FFMPEG_FORMATS ); +for ( my $i = 0; $i < @formats; $i++ ) +{ + if ( $i =~ /^(.+)\*$/ ) + { + $format = $formats[$i] = $1; + } +} + +sub Usage +{ + print( " +Usage: zmvideo.pl -e ,--event= [--format ] [--rate=] [--scale=] [--fps=] [--size=] [--overwrite] +Parameters are :- +-e, --event= - What event to create the video for +-f, --format= - What format to create the video in, default is mpg. For ffmpeg only. +-r, --rate= - Relative rate , 1 = realtime, 2 = double speed , 0.5 = half speed etc +-s, --scale= - Scale, 1 = normal, 2 = double size, 0.5 = half size etc +-F, --fps= - Absolute frame rate, in frames per second +-S, --size= - Absolute video size, WxH or other specification supported by ffmpeg +-o, --overwrite - Whether to overwrite an existing file, off by default. +"); + exit( -1 ); +} + +if ( !GetOptions( 'event=i'=>\$event_id, 'format|f=s'=>\$format, 'rate|r=f'=>\$rate, 'scale|s=f'=>\$scale, 'fps|F=f'=>\$fps, 'size|S=s'=>\$size, 'overwrite'=>\$overwrite ) ) +{ + Usage(); +} + +if ( !$event_id || $event_id < 0 ) +{ + print( STDERR "Please give a valid event id\n" ); + Usage(); +} + +if ( !ZM_OPT_FFMPEG ) +{ + print( STDERR "Mpeg encoding is not currently enabled\n" ); + exit(-1); +} + +if ( !$rate && !$fps ) +{ + $rate = 1; +} + +if ( !$scale && !$size ) +{ + $scale = 1; +} + +if ( $rate && ($rate < 0.25 || $rate > 100) ) +{ + print( STDERR "Rate is out of range, 0.25 >= rate <= 100\n" ); + Usage(); +} + +if ( $scale && ($scale < 0.25 || $scale > 4) ) +{ + print( STDERR "Scale is out of range, 0.25 >= scale <= 4\n" ); + Usage(); +} + +if ( $fps && ($fps > 30) ) +{ + print( STDERR "FPS is out of range, <= 30\n" ); + Usage(); +} + +my ( $detaint_format ) = $format =~ /^(\w+)$/; +my ( $detaint_rate ) = $rate =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_scale ) = $scale =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_fps ) = $fps =~ /^(-?\d+(?:\.\d+)?)$/; +my ( $detaint_size ) = $size =~ /^(\w+)$/; + +$format = $detaint_format; +$rate = $detaint_rate; +$scale = $detaint_scale; +$fps = $detaint_fps; +$size = $detaint_size; + +my $dbh = zmDbConnect(); + +my @filters; +my $sql = "select max(F.Delta)-min(F.Delta) as FullLength, E.*, unix_timestamp(E.StartTime) as Time, M.Name as MonitorName, M.Width as MonitorWidth, M.Height as MonitorHeight, M.Palette from Frames as F inner join Events as E on F.EventId = E.Id inner join Monitors as M on E.MonitorId = M.Id where EventId = '$event_id' group by F.EventId"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); +my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); +my $event = $sth->fetchrow_hashref(); +$sth->finish(); +my $event_path = getEventPath( $event ); +chdir( $event_path ); +( my $video_name = $event->{Name} ) =~ s/\s/_/g; + +my @file_parts; +if ( $rate ) +{ + my $file_rate = $rate; + $file_rate =~ s/\./_/; + $file_rate =~ s/_00//; + $file_rate =~ s/(_\d+)0+$/$1/; + $file_rate = 'r'.$file_rate; + push( @file_parts, $file_rate ); +} +elsif ( $fps ) +{ + my $file_fps = $fps; + $file_fps =~ s/\./_/; + $file_fps =~ s/_00//; + $file_fps =~ s/(_\d+)0+$/$1/; + $file_fps = 'R'.$file_fps; + push( @file_parts, $file_fps ); +} + +if ( $scale ) +{ + my $file_scale = $scale; + $file_scale =~ s/\./_/; + $file_scale =~ s/_00//; + $file_scale =~ s/(_\d+)0+$/$1/; + $file_scale = 's'.$file_scale; + push( @file_parts, $file_scale ); +} +elsif ( $size ) +{ + my $file_size = 'S'.$size; + push( @file_parts, $file_size ); +} +my $video_file = "$video_name-".$file_parts[0]."-".$file_parts[1].".$format"; + +if ( $overwrite || !-s $video_file ) +{ + Info( "Creating video file $video_file for event $event->{Id}\n" ); + + my $frame_rate = sprintf( "%.2f", $event->{Frames}/$event->{FullLength} ); + if ( $rate ) + { + if ( $rate != 1.0 ) + { + $frame_rate *= $rate; + } + } + elsif ( $fps ) + { + $frame_rate = $fps; + } + + my $width = $event->{MonitorWidth}; + my $height = $event->{MonitorHeight}; + my $video_size = " ${width}x${height}"; + + if ( $scale ) + { + if ( $scale != 1.0 ) + { + $width = int($width*$scale); + $height = int($height*$scale); + $video_size = " ${width}x${height}"; + } + } + elsif ( $size ) + { + $video_size = $size; + } + + my $command = ZM_PATH_FFMPEG." -y -r $frame_rate ".ZM_FFMPEG_INPUT_OPTIONS." -i %0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg -s $video_size ".ZM_FFMPEG_OUTPUT_OPTIONS." '$video_file' > ffmpeg.log 2>&1"; + Debug( $command."\n" ); + my $output = qx($command); + + my $status = $? >> 8; + if ( $status ) + { + Error( "Unable to generate video, check ".$event_path."/ffmpeg.log for details" ); + exit( -1 ); + } + + Info( "Finished $video_file\n" ); +} +else +{ + Info( "Video file $video_file already exists for event $event->{Id}\n" ); +} +#print( STDOUT $event->{MonitorId}.'/'.$event->{Id}.'/'.$video_file."\n" ); +print( STDOUT $video_file."\n" ); +exit( 0 ); diff --git a/scripts/zmwatch.pl b/scripts/zmwatch.pl new file mode 100644 index 000000000..5d16d3122 --- /dev/null +++ b/scripts/zmwatch.pl @@ -0,0 +1,148 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder WatchDog Script, $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 does some basic setup for ZoneMinder to run and then periodically +# checks the fps output of the active daemons to check they haven't +# locked up. If they have then they are killed and restarted +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant START_DELAY => 30; # To give everything else time to start + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use POSIX; +use DBI; +use Data::Dumper; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmwatch.pl +"); + exit( -1 ); +} + +logInit(); +logSetSignal(); + +Info( "Watchdog starting\n" ); +Info( "Watchdog pausing for ".START_DELAY." seconds\n" ); +sleep( START_DELAY ); + +my $dbh = zmDbConnect(); + +my $sql = "select * from Monitors"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + +while( 1 ) +{ + my $now = time(); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( $monitor->{Function} ne 'None' ) + { + my $restart = 0; + if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) ) + { + # Check we have got an image recently + my $image_time = zmGetLastWriteTime( $monitor ); + next if ( !defined($image_time) ); # Can't read from shared data + next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died. + + my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):ZM_WATCH_MAX_DELAY; + my $image_delay = $now-$image_time; + Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" ); + if ( $image_delay > $max_image_delay ) + { + Info( "Restarting capture daemon for ".$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n" ); + $restart = 1; + } + } + else + { + #Info( "Restarting capture daemon for ".$monitor->{Name}.", shared data not valid\n" ); + #$restart = 1; + } + + if ( $restart ) + { + my $command; + if ( $monitor->{Type} eq 'Local' ) + { + $command = "zmdc.pl restart zmc -d $monitor->{Device}"; + } + else + { + $command = "zmdc.pl restart zmc -m $monitor->{Id}"; + } + runCommand( $command ); + } + elsif ( $monitor->{Function} ne 'Monitor' ) + { + if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) ) + { + # Check we have got an image recently + my $image_time = zmGetLastReadTime( $monitor ); + next if ( !defined($image_time) ); # Can't read from shared data + next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died. + + my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):ZM_WATCH_MAX_DELAY; + my $image_delay = $now-$image_time; + Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" ); + if ( $image_delay > $max_image_delay ) + { + Info( "Restarting analysis daemon for ".$monitor->{Name}.", time since last analysis $image_delay seconds ($now-$image_time)\n" ); + my $command = "zmdc.pl restart zma -m ".$monitor->{Id}; + runCommand( $command ); + } + } + } + } + # Prevent open handles building up if we have connect to shared memory + zmMemInvalidate( $monitor ); + } + sleep( ZM_WATCH_CHECK_INTERVAL ); +} +Info( "Watchdog exiting\n" ); +exit(); diff --git a/scripts/zmwatch.pl.in b/scripts/zmwatch.pl.in new file mode 100644 index 000000000..4d50f0496 --- /dev/null +++ b/scripts/zmwatch.pl.in @@ -0,0 +1,148 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder WatchDog Script, $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 does some basic setup for ZoneMinder to run and then periodically +# checks the fps output of the active daemons to check they haven't +# locked up. If they have then they are killed and restarted +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant START_DELAY => 30; # To give everything else time to start + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use POSIX; +use DBI; +use Data::Dumper; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmwatch.pl +"); + exit( -1 ); +} + +logInit(); +logSetSignal(); + +Info( "Watchdog starting\n" ); +Info( "Watchdog pausing for ".START_DELAY." seconds\n" ); +sleep( START_DELAY ); + +my $dbh = zmDbConnect(); + +my $sql = "select * from Monitors"; +my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + +while( 1 ) +{ + my $now = time(); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + if ( $monitor->{Function} ne 'None' ) + { + my $restart = 0; + if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) ) + { + # Check we have got an image recently + my $image_time = zmGetLastWriteTime( $monitor ); + next if ( !defined($image_time) ); # Can't read from shared data + next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died. + + my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):ZM_WATCH_MAX_DELAY; + my $image_delay = $now-$image_time; + Debug( "Monitor $monitor->{Id} last captured $image_delay seconds ago, max is $max_image_delay\n" ); + if ( $image_delay > $max_image_delay ) + { + Info( "Restarting capture daemon for ".$monitor->{Name}.", time since last capture $image_delay seconds ($now-$image_time)\n" ); + $restart = 1; + } + } + else + { + #Info( "Restarting capture daemon for ".$monitor->{Name}.", shared data not valid\n" ); + #$restart = 1; + } + + if ( $restart ) + { + my $command; + if ( $monitor->{Type} eq 'Local' ) + { + $command = "zmdc.pl restart zmc -d $monitor->{Device}"; + } + else + { + $command = "zmdc.pl restart zmc -m $monitor->{Id}"; + } + runCommand( $command ); + } + elsif ( $monitor->{Function} ne 'Monitor' ) + { + if ( zmMemVerify( $monitor ) && zmMemRead( $monitor, "shared_data:valid" ) ) + { + # Check we have got an image recently + my $image_time = zmGetLastReadTime( $monitor ); + next if ( !defined($image_time) ); # Can't read from shared data + next if ( !$image_time ); # We can't get the last capture time so can't be sure it's died. + + my $max_image_delay = ($monitor->{MaxFPS}&&($monitor->{MaxFPS}>0)&&($monitor->{MaxFPS}<1))?(3/$monitor->{MaxFPS}):ZM_WATCH_MAX_DELAY; + my $image_delay = $now-$image_time; + Debug( "Monitor $monitor->{Id} last analysed $image_delay seconds ago, max is $max_image_delay\n" ); + if ( $image_delay > $max_image_delay ) + { + Info( "Restarting analysis daemon for ".$monitor->{Name}.", time since last analysis $image_delay seconds ($now-$image_time)\n" ); + my $command = "zmdc.pl restart zma -m ".$monitor->{Id}; + runCommand( $command ); + } + } + } + } + # Prevent open handles building up if we have connect to shared memory + zmMemInvalidate( $monitor ); + } + sleep( ZM_WATCH_CHECK_INTERVAL ); +} +Info( "Watchdog exiting\n" ); +exit(); diff --git a/scripts/zmx10.pl b/scripts/zmx10.pl new file mode 100644 index 000000000..936e18889 --- /dev/null +++ b/scripts/zmx10.pl @@ -0,0 +1,675 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder X10 Control Script, $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 script controls the monitoring of the X10 interface and the consequent +# management of the ZM daemons based on the receipt of X10 signals. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant CAUSE_STRING => "X10"; # What gets written as the cause of any events + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +use lib '/usr/share/perl/5.14.2'; # Include custom perl install path +use ZoneMinder; +use POSIX; +use Socket; +use Getopt::Long; +use Data::Dumper; + +use constant SOCK_FILE => ZM_PATH_SOCKS.'/zmx10.sock'; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmx10.pl -c ,--command= [-u ,--unit-code=] +Parameters are :- +-c , --command= - Command to issue, one of 'on','off','dim','bright','status','shutdown' +-u , --unit-code= - Unit code to act on required for all commands except 'status' (optional) and 'shutdown' +"); + exit( -1 ); +} + +logInit(); +logSetSignal(); + +my $command; +my $unit_code; + +if ( !GetOptions( 'command=s'=>\$command, 'unit-code=i'=>\$unit_code ) ) +{ + Usage(); +} + +die( "No command given" ) unless( $command ); +die( "No unit code given" ) unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) ); + +if ( $command eq "start" ) +{ + X10Server::runServer(); + exit(); +} + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( SOCK_FILE ); + +if ( !connect( CLIENT, $saddr ) ) +{ + # The server isn't there + print( "Unable to connect, starting server\n" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + # Parent process just sleep and fall through + sleep( 2 ); + logReinit(); + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + connect( CLIENT, $saddr ) or Fatal( "Can't connect: $!" ); + } + elsif ( defined($cpid) ) + { + setpgrp(); + + logReinit(); + X10Server::runServer(); + } + else + { + Fatal( "Can't fork: $!" ); + } +} +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); +my $message = "$command"; +$message .= ";$unit_code" if ( $unit_code ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); +while ( my $line = ) +{ + chomp( $line ); + print( "$line\n" ); +} +close( CLIENT ); +#print( "Finished writing, bye\n" ); +exit; + +# +# ========================================================================== +# +# This is the X10 Server package +# +# ========================================================================== +# +package X10Server; + +use strict; +use bytes; + +use ZoneMinder; +use POSIX; +use DBI; +use Socket; +use X10::ActiveHome; +use Data::Dumper; + +our $dbh; +our $x10; + +our %monitor_hash; +our %device_hash; +our %pending_tasks; + +sub runServer +{ + Info( "X10 server starting\n" ); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( main::SOCK_FILE ); + my $saddr = sockaddr_un( main::SOCK_FILE ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + $dbh = zmDbConnect(); + + $x10 = new X10::ActiveHome( port=>ZM_X10_DEVICE, house_code=>ZM_X10_HOUSE_CODE, debug=>0 ); + + loadTasks(); + + $x10->register_listener( \&x10listen ); + + my $rin = ''; + vec( $rin, fileno(SERVER),1) = 1; + vec( $rin, $x10->select_fds(),1) = 1; + my $timeout = 0.2; + #print( "F:".fileno(SERVER)."\n" ); + my $reload = undef; + my $reload_count = 0; + my $reload_limit = &ZM_X10_DB_RELOAD_INTERVAL / $timeout; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + #print( "Off select, NF:$nfound, ER:$!\n" ); + #print( vec( $rout, fileno(SERVER),1)."\n" ); + #print( vec( $rout, $x10->select_fds(),1)."\n" ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER),1) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + my ( $command, $unit_code ) = split( /;/, $message ); + + my $device; + if ( defined($unit_code) ) + { + if ( $unit_code < 1 || $unit_code > 16 ) + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid unit code '$unit_code'\n" ); + next; + } + + $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + } + + my $result; + if ( $command eq 'on' ) + { + $result = $device->{appliance}->on(); + } + elsif ( $command eq 'off' ) + { + $result = $device->{appliance}->off(); + } + #elsif ( $command eq 'dim' ) + #{ + #$result = $device->{appliance}->dim(); + #} + #elsif ( $command eq 'bright' ) + #{ + #$result = $device->{appliance}->bright(); + #} + elsif ( $command eq 'status' ) + { + if ( $device ) + { + dPrint( ZoneMinder::Logger::DEBUG, $unit_code." ".$device->{status}."\n" ); + } + else + { + foreach my $unit_code ( sort( keys(%device_hash) ) ) + { + my $device = $device_hash{$unit_code}; + dPrint( ZoneMinder::Logger::DEBUG, $unit_code." ".$device->{status}."\n" ); + } + } + } + elsif ( $command eq 'shutdown' ) + { + last; + } + else + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" ); + } + if ( defined($result) ) + { + if ( 1 || $result ) + { + $device->{status} = uc($command); + dPrint( ZoneMinder::Logger::DEBUG, $device->{appliance}->address()." $command, ok\n" ); + #x10listen( new X10::Event( sprintf("%s %s", $device->{appliance}->address, uc($command) ) ) ); + } + else + { + dPrint( ZoneMinder::Logger::ERROR, $device->{appliance}->address()." $command, failed\n" ); + } + } + close( CLIENT ); + } + elsif ( vec( $rout, $x10->select_fds(),1) ) + { + $x10->handle_input(); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! != EINTR ) + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + # Check for state changes + foreach my $monitor_id ( sort(keys(%monitor_hash) ) ) + { + my $monitor = $monitor_hash{$monitor_id}; + my $state = zmGetMonitorState( $monitor ); + if ( !defined($state) ) + { + $reload = !undef; + next; + } + if ( defined( $monitor->{LastState} ) ) + { + my $task_list; + if ( ($state == STATE_ALARM || $state == STATE_ALERT) && ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE) ) # Gone into alarm state + { + Debug( "Applying ON_list for $monitor_id\n" ); + $task_list = $monitor->{"ON_list"}; + } + elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Come out of alarm state + { + Debug( "Applying OFF_list for $monitor_id\n" ); + $task_list = $monitor->{"OFF_list"}; + } + if ( $task_list ) + { + foreach my $task ( @$task_list ) + { + processTask( $task ); + } + } + } + $monitor->{LastState} = $state; + } + + # Check for pending tasks + my $now = time(); + foreach my $activation_time ( sort(keys(%pending_tasks) ) ) + { + last if ( $activation_time > $now ); + my $pending_list = $pending_tasks{$activation_time}; + foreach my $task ( @$pending_list ) + { + processTask( $task ); + } + delete( $pending_tasks{$activation_time} ); + } + if ( $reload || ++$reload_count >= $reload_limit ) + { + loadTasks(); + $reload = undef; + $reload_count = 0; + } + } + } + Info( "X10 server exiting\n" ); + close( SERVER ); + exit(); +} + +sub addToDeviceList +{ + my $unit_code = shift; + my $event = shift; + my $monitor = shift; + my $function = shift; + my $limit = shift; + + Debug( "Adding to device list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + + my $task = { type=>"device", monitor=>$monitor, address=>$device->{appliance}->address(), function=>$function }; + if ( $limit ) + { + $task->{limit} = $limit + } + + my $task_list = $device->{$event."_list"}; + if ( !$task_list ) + { + $task_list = $device->{$event."_list"} = []; + } + push( @$task_list, $task ); +} + +sub addToMonitorList +{ + my $monitor = shift; + my $event = shift; + my $unit_code = shift; + my $function = shift; + my $limit = shift; + + Debug( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + + my $task = { type=>"monitor", device=>$device, id=>$monitor->{Id}, function=>$function }; + if ( $limit ) + { + $task->{limit} = $limit; + } + + my $task_list = $monitor->{$event."_list"}; + if ( !$task_list ) + { + $task_list = $monitor->{$event."_list"} = []; + } + push( @$task_list, $task ); +} + +sub loadTasks +{ + %monitor_hash = (); + + Debug( "Loading tasks\n" ); + # Clear out all old device task lists + foreach my $unit_code ( sort( keys(%device_hash) ) ) + { + my $device = $device_hash{$unit_code}; + $device->{ON_list} = []; + $device->{OFF_list} = []; + } + + my $sql = "select M.*,T.* from Monitors as M inner join TriggersX10 as T on (M.Id = T.MonitorId) where find_in_set( M.Function, 'Modect,Record,Mocord,Nodect' ) and M.Enabled = 1 and find_in_set( 'X10', M.Triggers )"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok + + $monitor_hash{$monitor->{Id}} = $monitor; + + if ( $monitor->{Activation} ) + { + Debug( "$monitor->{Name} has active string '$monitor->{Activation}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{Activation} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_active":"stop_active", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_active":"start_active", $limit ); + } + } + } + } + if ( $monitor->{AlarmInput} ) + { + Debug( "$monitor->{Name} has alarm input string '$monitor->{AlarmInput}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{AlarmInput} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_alarm":"stop_alarm", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_alarm":"start_alarm", $limit ); + } + } + } + } + if ( $monitor->{AlarmOutput} ) + { + Debug( "$monitor->{Name} has alarm output string '$monitor->{AlarmOutput}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{AlarmOutput} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToMonitorList( $monitor, "ON", $unit_code, !$invert?"on":"off", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToMonitorList( $monitor, "OFF", $unit_code, !$invert?"off":"on", $limit ); + } + } + } + } + zmMemInvalidate( $monitor ); + } +} + +sub addPendingTask +{ + my $task = shift; + + # Check whether we are just extending a previous pending task + # and remove it if it's there + foreach my $activation_time ( sort(keys(%pending_tasks) ) ) + { + my $pending_list = $pending_tasks{$activation_time}; + my $new_pending_list = []; + foreach my $pending_task ( @$pending_list ) + { + if ( $task->{type} ne $pending_task->{type} ) + { + push( @$new_pending_list, $pending_task ) + } + elsif ( $task->{type} eq "device" ) + { + if (( $task->{monitor}->{Id} != $pending_task->{monitor}->{Id} ) + || ( $task->{function} ne $pending_task->{function} )) + { + push( @$new_pending_list, $pending_task ) + } + } + elsif ( $task->{type} eq "monitor" ) + { + if (( $task->{device}->{appliance}->unit_code() != $pending_task->{device}->{appliance}->unit_code() ) + || ( $task->{function} ne $pending_task->{function} )) + { + push( @$new_pending_list, $pending_task ) + } + } + } + if ( @$new_pending_list ) + { + $pending_tasks{$activation_time} = $new_pending_list; + } + else + { + delete( $pending_tasks{$activation_time} ); + } + } + + my $end_time = time() + $task->{limit}; + my $pending_list = $pending_tasks{$end_time}; + if ( !$pending_list ) + { + $pending_list = $pending_tasks{$end_time} = []; + } + my $pending_task; + if ( $task->{type} eq "device" ) + { + $pending_task = { type=>$task->{type}, monitor=>$task->{monitor}, function=>$task->{function} }; + $pending_task->{function} =~ s/start/stop/; + } + elsif ( $task->{type} eq "monitor" ) + { + $pending_task = { type=>$task->{type}, device=>$task->{device}, function=>$task->{function} }; + $pending_task->{function} =~ s/on/off/; + } + push( @$pending_list, $pending_task ); +} + +sub processTask +{ + my $task = shift; + + if ( $task->{type} eq "device" ) + { + my ( $instruction, $class ) = ( $task->{function} =~ /^(.+)_(.+)$/ ); + + if ( $class eq "active" ) + { + if ( $instruction eq "start" ) + { + zmMonitorEnable( $task->{monitor} ); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif( $instruction eq "stop" ) + { + zmMonitorDisable( $task->{monitor} ); + } + } + elsif( $class eq "alarm" ) + { + if ( $instruction eq "start" ) + { + zmTriggerEventOn( $task->{monitor}, 0, main::CAUSE_STRING, $task->{address} ); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif( $instruction eq "stop" ) + { + zmTriggerEventCancel( $task->{monitor} ); + } + } + } + elsif( $task->{type} eq "monitor" ) + { + if ( $task->{function} eq "on" ) + { + $task->{device}->{appliance}->on(); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif ( $task->{function} eq "off" ) + { + $task->{device}->{appliance}->off(); + } + } +} + +sub dPrint +{ + my $dbg_level = shift; + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } + if ( $dbg_level == ZoneMinder::Logger::DEBUG ) + { + Debug( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::INFO ) + { + Info( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::WARNING ) + { + Warning( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::ERROR ) + { + Error( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::FATAL ) + { + Fatal( @_ ); + } +} + +sub x10listen +{ + foreach my $event ( @_ ) + { + #print( Data::Dumper( $_ )."\n" ); + if ( $event->house_code() eq ZM_X10_HOUSE_CODE ) + { + my $unit_code = $event->unit_code(); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + next if ( $event->func() !~ /(?:ON|OFF)/ ); + $device->{status} = $event->func(); + my $task_list = $device->{$event->func()."_list"}; + if ( $task_list ) + { + foreach my $task ( @$task_list ) + { + processTask( $task ); + } + } + } + Info( "Got event - ".$event->as_string()."\n" ); + } +} + +1; diff --git a/scripts/zmx10.pl.in b/scripts/zmx10.pl.in new file mode 100644 index 000000000..14eff5a01 --- /dev/null +++ b/scripts/zmx10.pl.in @@ -0,0 +1,675 @@ +#!/usr/bin/perl -wT +# +# ========================================================================== +# +# ZoneMinder X10 Control Script, $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 script controls the monitoring of the X10 interface and the consequent +# management of the ZM daemons based on the receipt of X10 signals. +# +use strict; +use bytes; + +# ========================================================================== +# +# These are the elements you can edit to suit your installation +# +# ========================================================================== + +use constant CAUSE_STRING => "X10"; # What gets written as the cause of any events + +# ========================================================================== +# +# Don't change anything below here +# +# ========================================================================== + +@EXTRA_PERL_LIB@ +use ZoneMinder; +use POSIX; +use Socket; +use Getopt::Long; +use Data::Dumper; + +use constant SOCK_FILE => ZM_PATH_SOCKS.'/zmx10.sock'; + +$| = 1; + +$ENV{PATH} = '/bin:/usr/bin'; +$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL}; +delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; + +sub Usage +{ + print( " +Usage: zmx10.pl -c ,--command= [-u ,--unit-code=] +Parameters are :- +-c , --command= - Command to issue, one of 'on','off','dim','bright','status','shutdown' +-u , --unit-code= - Unit code to act on required for all commands except 'status' (optional) and 'shutdown' +"); + exit( -1 ); +} + +logInit(); +logSetSignal(); + +my $command; +my $unit_code; + +if ( !GetOptions( 'command=s'=>\$command, 'unit-code=i'=>\$unit_code ) ) +{ + Usage(); +} + +die( "No command given" ) unless( $command ); +die( "No unit code given" ) unless( $unit_code || ($command =~ /(?:start|status|shutdown)/) ); + +if ( $command eq "start" ) +{ + X10Server::runServer(); + exit(); +} + +socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + +my $saddr = sockaddr_un( SOCK_FILE ); + +if ( !connect( CLIENT, $saddr ) ) +{ + # The server isn't there + print( "Unable to connect, starting server\n" ); + close( CLIENT ); + + if ( my $cpid = fork() ) + { + # Parent process just sleep and fall through + sleep( 2 ); + logReinit(); + socket( CLIENT, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + connect( CLIENT, $saddr ) or Fatal( "Can't connect: $!" ); + } + elsif ( defined($cpid) ) + { + setpgrp(); + + logReinit(); + X10Server::runServer(); + } + else + { + Fatal( "Can't fork: $!" ); + } +} +# The server is there, connect to it +#print( "Writing commands\n" ); +CLIENT->autoflush(); +my $message = "$command"; +$message .= ";$unit_code" if ( $unit_code ); +print( CLIENT $message ); +shutdown( CLIENT, 1 ); +while ( my $line = ) +{ + chomp( $line ); + print( "$line\n" ); +} +close( CLIENT ); +#print( "Finished writing, bye\n" ); +exit; + +# +# ========================================================================== +# +# This is the X10 Server package +# +# ========================================================================== +# +package X10Server; + +use strict; +use bytes; + +use ZoneMinder; +use POSIX; +use DBI; +use Socket; +use X10::ActiveHome; +use Data::Dumper; + +our $dbh; +our $x10; + +our %monitor_hash; +our %device_hash; +our %pending_tasks; + +sub runServer +{ + Info( "X10 server starting\n" ); + + socket( SERVER, PF_UNIX, SOCK_STREAM, 0 ) or Fatal( "Can't open socket: $!" ); + unlink( main::SOCK_FILE ); + my $saddr = sockaddr_un( main::SOCK_FILE ); + bind( SERVER, $saddr ) or Fatal( "Can't bind: $!" ); + listen( SERVER, SOMAXCONN ) or Fatal( "Can't listen: $!" ); + + $dbh = zmDbConnect(); + + $x10 = new X10::ActiveHome( port=>ZM_X10_DEVICE, house_code=>ZM_X10_HOUSE_CODE, debug=>0 ); + + loadTasks(); + + $x10->register_listener( \&x10listen ); + + my $rin = ''; + vec( $rin, fileno(SERVER),1) = 1; + vec( $rin, $x10->select_fds(),1) = 1; + my $timeout = 0.2; + #print( "F:".fileno(SERVER)."\n" ); + my $reload = undef; + my $reload_count = 0; + my $reload_limit = &ZM_X10_DB_RELOAD_INTERVAL / $timeout; + while( 1 ) + { + my $nfound = select( my $rout = $rin, undef, undef, $timeout ); + #print( "Off select, NF:$nfound, ER:$!\n" ); + #print( vec( $rout, fileno(SERVER),1)."\n" ); + #print( vec( $rout, $x10->select_fds(),1)."\n" ); + if ( $nfound > 0 ) + { + if ( vec( $rout, fileno(SERVER),1) ) + { + my $paddr = accept( CLIENT, SERVER ); + my $message = ; + + my ( $command, $unit_code ) = split( /;/, $message ); + + my $device; + if ( defined($unit_code) ) + { + if ( $unit_code < 1 || $unit_code > 16 ) + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid unit code '$unit_code'\n" ); + next; + } + + $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + } + + my $result; + if ( $command eq 'on' ) + { + $result = $device->{appliance}->on(); + } + elsif ( $command eq 'off' ) + { + $result = $device->{appliance}->off(); + } + #elsif ( $command eq 'dim' ) + #{ + #$result = $device->{appliance}->dim(); + #} + #elsif ( $command eq 'bright' ) + #{ + #$result = $device->{appliance}->bright(); + #} + elsif ( $command eq 'status' ) + { + if ( $device ) + { + dPrint( ZoneMinder::Logger::DEBUG, $unit_code." ".$device->{status}."\n" ); + } + else + { + foreach my $unit_code ( sort( keys(%device_hash) ) ) + { + my $device = $device_hash{$unit_code}; + dPrint( ZoneMinder::Logger::DEBUG, $unit_code." ".$device->{status}."\n" ); + } + } + } + elsif ( $command eq 'shutdown' ) + { + last; + } + else + { + dPrint( ZoneMinder::Logger::ERROR, "Invalid command '$command'\n" ); + } + if ( defined($result) ) + { + if ( 1 || $result ) + { + $device->{status} = uc($command); + dPrint( ZoneMinder::Logger::DEBUG, $device->{appliance}->address()." $command, ok\n" ); + #x10listen( new X10::Event( sprintf("%s %s", $device->{appliance}->address, uc($command) ) ) ); + } + else + { + dPrint( ZoneMinder::Logger::ERROR, $device->{appliance}->address()." $command, failed\n" ); + } + } + close( CLIENT ); + } + elsif ( vec( $rout, $x10->select_fds(),1) ) + { + $x10->handle_input(); + } + else + { + Fatal( "Bogus descriptor" ); + } + } + elsif ( $nfound < 0 ) + { + if ( $! != EINTR ) + { + Fatal( "Can't select: $!" ); + } + } + else + { + #print( "Select timed out\n" ); + # Check for state changes + foreach my $monitor_id ( sort(keys(%monitor_hash) ) ) + { + my $monitor = $monitor_hash{$monitor_id}; + my $state = zmGetMonitorState( $monitor ); + if ( !defined($state) ) + { + $reload = !undef; + next; + } + if ( defined( $monitor->{LastState} ) ) + { + my $task_list; + if ( ($state == STATE_ALARM || $state == STATE_ALERT) && ($monitor->{LastState} == STATE_IDLE || $monitor->{LastState} == STATE_TAPE) ) # Gone into alarm state + { + Debug( "Applying ON_list for $monitor_id\n" ); + $task_list = $monitor->{"ON_list"}; + } + elsif ( ($state == STATE_IDLE && $monitor->{LastState} != STATE_IDLE) || ($state == STATE_TAPE && $monitor->{LastState} != STATE_TAPE) ) # Come out of alarm state + { + Debug( "Applying OFF_list for $monitor_id\n" ); + $task_list = $monitor->{"OFF_list"}; + } + if ( $task_list ) + { + foreach my $task ( @$task_list ) + { + processTask( $task ); + } + } + } + $monitor->{LastState} = $state; + } + + # Check for pending tasks + my $now = time(); + foreach my $activation_time ( sort(keys(%pending_tasks) ) ) + { + last if ( $activation_time > $now ); + my $pending_list = $pending_tasks{$activation_time}; + foreach my $task ( @$pending_list ) + { + processTask( $task ); + } + delete( $pending_tasks{$activation_time} ); + } + if ( $reload || ++$reload_count >= $reload_limit ) + { + loadTasks(); + $reload = undef; + $reload_count = 0; + } + } + } + Info( "X10 server exiting\n" ); + close( SERVER ); + exit(); +} + +sub addToDeviceList +{ + my $unit_code = shift; + my $event = shift; + my $monitor = shift; + my $function = shift; + my $limit = shift; + + Debug( "Adding to device list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + + my $task = { type=>"device", monitor=>$monitor, address=>$device->{appliance}->address(), function=>$function }; + if ( $limit ) + { + $task->{limit} = $limit + } + + my $task_list = $device->{$event."_list"}; + if ( !$task_list ) + { + $task_list = $device->{$event."_list"} = []; + } + push( @$task_list, $task ); +} + +sub addToMonitorList +{ + my $monitor = shift; + my $event = shift; + my $unit_code = shift; + my $function = shift; + my $limit = shift; + + Debug( "Adding to monitor list, uc:$unit_code, ev:$event, mo:".$monitor->{Id}.", fu:$function, li:$limit\n" ); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + + my $task = { type=>"monitor", device=>$device, id=>$monitor->{Id}, function=>$function }; + if ( $limit ) + { + $task->{limit} = $limit; + } + + my $task_list = $monitor->{$event."_list"}; + if ( !$task_list ) + { + $task_list = $monitor->{$event."_list"} = []; + } + push( @$task_list, $task ); +} + +sub loadTasks +{ + %monitor_hash = (); + + Debug( "Loading tasks\n" ); + # Clear out all old device task lists + foreach my $unit_code ( sort( keys(%device_hash) ) ) + { + my $device = $device_hash{$unit_code}; + $device->{ON_list} = []; + $device->{OFF_list} = []; + } + + my $sql = "select M.*,T.* from Monitors as M inner join TriggersX10 as T on (M.Id = T.MonitorId) where find_in_set( M.Function, 'Modect,Record,Mocord,Nodect' ) and M.Enabled = 1 and find_in_set( 'X10', M.Triggers )"; + my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); + my $res = $sth->execute() or Fatal( "Can't execute: ".$sth->errstr() ); + while( my $monitor = $sth->fetchrow_hashref() ) + { + next if ( !zmMemVerify( $monitor ) ); # Check shared memory ok + + $monitor_hash{$monitor->{Id}} = $monitor; + + if ( $monitor->{Activation} ) + { + Debug( "$monitor->{Name} has active string '$monitor->{Activation}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{Activation} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_active":"stop_active", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_active":"start_active", $limit ); + } + } + } + } + if ( $monitor->{AlarmInput} ) + { + Debug( "$monitor->{Name} has alarm input string '$monitor->{AlarmInput}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{AlarmInput} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToDeviceList( $unit_code, "ON", $monitor, !$invert?"start_alarm":"stop_alarm", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToDeviceList( $unit_code, "OFF", $monitor, !$invert?"stop_alarm":"start_alarm", $limit ); + } + } + } + } + if ( $monitor->{AlarmOutput} ) + { + Debug( "$monitor->{Name} has alarm output string '$monitor->{AlarmOutput}'\n" ); + foreach my $code_string ( split( /,/, $monitor->{AlarmOutput} ) ) + { + #Debug( "Code string: $code_string\n" ); + my ( $invert, $unit_code, $modifier, $limit ) = ( $code_string =~ /^([!~])?(\d+)(?:([+-])(\d+)?)?$/ ); + $limit = 0 if ( !$limit ); + if ( $unit_code ) + { + if ( !$modifier || $modifier eq '+' ) + { + addToMonitorList( $monitor, "ON", $unit_code, !$invert?"on":"off", $limit ); + } + if ( !$modifier || $modifier eq '-' ) + { + addToMonitorList( $monitor, "OFF", $unit_code, !$invert?"off":"on", $limit ); + } + } + } + } + zmMemInvalidate( $monitor ); + } +} + +sub addPendingTask +{ + my $task = shift; + + # Check whether we are just extending a previous pending task + # and remove it if it's there + foreach my $activation_time ( sort(keys(%pending_tasks) ) ) + { + my $pending_list = $pending_tasks{$activation_time}; + my $new_pending_list = []; + foreach my $pending_task ( @$pending_list ) + { + if ( $task->{type} ne $pending_task->{type} ) + { + push( @$new_pending_list, $pending_task ) + } + elsif ( $task->{type} eq "device" ) + { + if (( $task->{monitor}->{Id} != $pending_task->{monitor}->{Id} ) + || ( $task->{function} ne $pending_task->{function} )) + { + push( @$new_pending_list, $pending_task ) + } + } + elsif ( $task->{type} eq "monitor" ) + { + if (( $task->{device}->{appliance}->unit_code() != $pending_task->{device}->{appliance}->unit_code() ) + || ( $task->{function} ne $pending_task->{function} )) + { + push( @$new_pending_list, $pending_task ) + } + } + } + if ( @$new_pending_list ) + { + $pending_tasks{$activation_time} = $new_pending_list; + } + else + { + delete( $pending_tasks{$activation_time} ); + } + } + + my $end_time = time() + $task->{limit}; + my $pending_list = $pending_tasks{$end_time}; + if ( !$pending_list ) + { + $pending_list = $pending_tasks{$end_time} = []; + } + my $pending_task; + if ( $task->{type} eq "device" ) + { + $pending_task = { type=>$task->{type}, monitor=>$task->{monitor}, function=>$task->{function} }; + $pending_task->{function} =~ s/start/stop/; + } + elsif ( $task->{type} eq "monitor" ) + { + $pending_task = { type=>$task->{type}, device=>$task->{device}, function=>$task->{function} }; + $pending_task->{function} =~ s/on/off/; + } + push( @$pending_list, $pending_task ); +} + +sub processTask +{ + my $task = shift; + + if ( $task->{type} eq "device" ) + { + my ( $instruction, $class ) = ( $task->{function} =~ /^(.+)_(.+)$/ ); + + if ( $class eq "active" ) + { + if ( $instruction eq "start" ) + { + zmMonitorEnable( $task->{monitor} ); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif( $instruction eq "stop" ) + { + zmMonitorDisable( $task->{monitor} ); + } + } + elsif( $class eq "alarm" ) + { + if ( $instruction eq "start" ) + { + zmTriggerEventOn( $task->{monitor}, 0, main::CAUSE_STRING, $task->{address} ); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif( $instruction eq "stop" ) + { + zmTriggerEventCancel( $task->{monitor} ); + } + } + } + elsif( $task->{type} eq "monitor" ) + { + if ( $task->{function} eq "on" ) + { + $task->{device}->{appliance}->on(); + if ( $task->{limit} ) + { + addPendingTask( $task ); + } + } + elsif ( $task->{function} eq "off" ) + { + $task->{device}->{appliance}->off(); + } + } +} + +sub dPrint +{ + my $dbg_level = shift; + if ( fileno(CLIENT) ) + { + print CLIENT @_ + } + if ( $dbg_level == ZoneMinder::Logger::DEBUG ) + { + Debug( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::INFO ) + { + Info( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::WARNING ) + { + Warning( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::ERROR ) + { + Error( @_ ); + } + elsif ( $dbg_level == ZoneMinder::Logger::FATAL ) + { + Fatal( @_ ); + } +} + +sub x10listen +{ + foreach my $event ( @_ ) + { + #print( Data::Dumper( $_ )."\n" ); + if ( $event->house_code() eq ZM_X10_HOUSE_CODE ) + { + my $unit_code = $event->unit_code(); + my $device = $device_hash{$unit_code}; + if ( !$device ) + { + $device = $device_hash{$unit_code} = { appliance=>$x10->Appliance( unit_code=>$unit_code ), status=>'unknown' }; + } + next if ( $event->func() !~ /(?:ON|OFF)/ ); + $device->{status} = $event->func(); + my $task_list = $device->{$event->func()."_list"}; + if ( $task_list ) + { + foreach my $task ( @$task_list ) + { + processTask( $task ); + } + } + } + Info( "Got event - ".$event->as_string()."\n" ); + } +} + +1; diff --git a/src/.deps/zm.Po b/src/.deps/zm.Po new file mode 100644 index 000000000..aa5176d0d --- /dev/null +++ b/src/.deps/zm.Po @@ -0,0 +1,269 @@ +zm.o: zm.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: diff --git a/src/.deps/zm_box.Po b/src/.deps/zm_box.Po new file mode 100644 index 000000000..1846ae588 --- /dev/null +++ b/src/.deps/zm_box.Po @@ -0,0 +1,297 @@ +zm_box.o: zm_box.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_box.h zm_coord.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_box.h: + +zm_coord.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: diff --git a/src/.deps/zm_buffer.Po b/src/.deps/zm_buffer.Po new file mode 100644 index 000000000..15df85a25 --- /dev/null +++ b/src/.deps/zm_buffer.Po @@ -0,0 +1,275 @@ +zm_buffer.o: zm_buffer.cpp /usr/include/string.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_buffer.h + +/usr/include/string.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_buffer.h: diff --git a/src/.deps/zm_camera.Po b/src/.deps/zm_camera.Po new file mode 100644 index 000000000..e9ac27af4 --- /dev/null +++ b/src/.deps/zm_camera.Po @@ -0,0 +1,418 @@ +zm_camera.o: zm_camera.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_camera.h /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: diff --git a/src/.deps/zm_comms.Po b/src/.deps/zm_comms.Po new file mode 100644 index 000000000..42f6a4dd1 --- /dev/null +++ b/src/.deps/zm_comms.Po @@ -0,0 +1,439 @@ +zm_comms.o: zm_comms.cpp zm_comms.h zm_exception.h zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + /usr/include/netdb.h /usr/include/netinet/in.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/string.h \ + /usr/include/c++/4.7/set /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h \ + /usr/include/x86_64-linux-gnu/sys/param.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/linux/param.h /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h /usr/include/netinet/tcp.h + +zm_comms.h: + +zm_exception.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/string.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +/usr/include/netinet/tcp.h: diff --git a/src/.deps/zm_config.Po b/src/.deps/zm_config.Po new file mode 100644 index 000000000..7301b983d --- /dev/null +++ b/src/.deps/zm_config.Po @@ -0,0 +1,310 @@ +zm_config.o: zm_config.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: diff --git a/src/.deps/zm_coord.Po b/src/.deps/zm_coord.Po new file mode 100644 index 000000000..2c657d78e --- /dev/null +++ b/src/.deps/zm_coord.Po @@ -0,0 +1,272 @@ +zm_coord.o: zm_coord.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_coord.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_coord.h: diff --git a/src/.deps/zm_db.Po b/src/.deps/zm_db.Po new file mode 100644 index 000000000..024e31879 --- /dev/null +++ b/src/.deps/zm_db.Po @@ -0,0 +1,285 @@ +zm_db.o: zm_db.cpp /usr/include/stdlib.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/string.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h + +/usr/include/stdlib.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: diff --git a/src/.deps/zm_detector.Po b/src/.deps/zm_detector.Po new file mode 100644 index 000000000..c4097bcbb --- /dev/null +++ b/src/.deps/zm_detector.Po @@ -0,0 +1,548 @@ +zm_detector.o: zm_detector.cpp zm_detector.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc /usr/include/syslog.h \ + /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_image.h zm.h zm_config.h ../config.h zm_config_defines.h zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h + +zm_detector.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_image.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: diff --git a/src/.deps/zm_event.Po b/src/.deps/zm_event.Po new file mode 100644 index 000000000..708c0e478 --- /dev/null +++ b/src/.deps/zm_event.Po @@ -0,0 +1,758 @@ +zm_event.o: zm_event.cpp /usr/include/fcntl.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/fcntl.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h /usr/include/arpa/inet.h \ + /usr/include/netinet/in.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/x86_64-linux-gnu/bits/in.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/string.h \ + /usr/include/xlocale.h /usr/include/x86_64-linux-gnu/sys/ipc.h \ + /usr/include/x86_64-linux-gnu/bits/ipctypes.h \ + /usr/include/x86_64-linux-gnu/bits/ipc.h \ + /usr/include/x86_64-linux-gnu/sys/msg.h \ + /usr/include/x86_64-linux-gnu/bits/msq.h /usr/include/getopt.h \ + /usr/include/glob.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h zm_db.h \ + zm_time.h /usr/include/x86_64-linux-gnu/sys/time.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/errno.h /usr/include/x86_64-linux-gnu/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + zm_event.h /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/c++/4.7/set /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + zm_poly.h zm_mem_utils.h zm_utils.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/zlib.h \ + /usr/include/zconf.h zm_stream.h zm_monitor.h \ + /usr/include/c++/4.7/sstream /usr/include/c++/4.7/istream \ + /usr/include/c++/4.7/ios /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_zone.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h zmf.h \ + /usr/include/x86_64-linux-gnu/sys/sendfile.h + +/usr/include/fcntl.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/fcntl.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/arpa/inet.h: + +/usr/include/netinet/in.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/string.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/ipc.h: + +/usr/include/x86_64-linux-gnu/bits/ipctypes.h: + +/usr/include/x86_64-linux-gnu/bits/ipc.h: + +/usr/include/x86_64-linux-gnu/sys/msg.h: + +/usr/include/x86_64-linux-gnu/bits/msq.h: + +/usr/include/getopt.h: + +/usr/include/glob.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +zm_db.h: + +zm_time.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +zm_event.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_stream.h: + +zm_monitor.h: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_zone.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: + +zmf.h: + +/usr/include/x86_64-linux-gnu/sys/sendfile.h: diff --git a/src/.deps/zm_exception.Po b/src/.deps/zm_exception.Po new file mode 100644 index 000000000..d726ff59f --- /dev/null +++ b/src/.deps/zm_exception.Po @@ -0,0 +1,271 @@ +zm_exception.o: zm_exception.cpp zm_exception.h zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h + +zm_exception.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: diff --git a/src/.deps/zm_ffmpeg.Po b/src/.deps/zm_ffmpeg.Po new file mode 100644 index 000000000..98bf6cb96 --- /dev/null +++ b/src/.deps/zm_ffmpeg.Po @@ -0,0 +1 @@ +zm_ffmpeg.o: zm_ffmpeg.cpp diff --git a/src/.deps/zm_ffmpeg_camera.Po b/src/.deps/zm_ffmpeg_camera.Po new file mode 100644 index 000000000..2045c0670 --- /dev/null +++ b/src/.deps/zm_ffmpeg_camera.Po @@ -0,0 +1,516 @@ +zm_ffmpeg_camera.o: zm_ffmpeg_camera.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_ffmpeg_camera.h zm_camera.h /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_buffer.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_ffmpeg_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_buffer.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: diff --git a/src/.deps/zm_file_camera.Po b/src/.deps/zm_file_camera.Po new file mode 100644 index 000000000..80f377c6a --- /dev/null +++ b/src/.deps/zm_file_camera.Po @@ -0,0 +1,498 @@ +zm_file_camera.o: zm_file_camera.cpp /usr/include/stdio.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/syslog.h \ + /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_file_camera.h zm_camera.h /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/zlib.h \ + /usr/include/zconf.h zm_buffer.h zm_regexp.h /usr/include/pcre.h \ + /usr/include/x86_64-linux-gnu/sys/param.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/linux/param.h /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_file_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_buffer.h: + +zm_regexp.h: + +/usr/include/pcre.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: diff --git a/src/.deps/zm_image.Po b/src/.deps/zm_image.Po new file mode 100644 index 000000000..3e0f05e9e --- /dev/null +++ b/src/.deps/zm_image.Po @@ -0,0 +1,399 @@ +zm_image.o: zm_image.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_font.h zm_image.h zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_font.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: diff --git a/src/.deps/zm_image_analyser.Po b/src/.deps/zm_image_analyser.Po new file mode 100644 index 000000000..af11ee9b9 --- /dev/null +++ b/src/.deps/zm_image_analyser.Po @@ -0,0 +1,627 @@ +zm_image_analyser.o: zm_image_analyser.cpp zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/stl_list.h /usr/include/c++/4.7/bits/list.tcc \ + /usr/include/c++/4.7/string /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/postypes.h /usr/include/c++/4.7/cwchar \ + /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc \ + /usr/include/c++/4.7/stdexcept /usr/include/c++/4.7/iostream \ + /usr/include/c++/4.7/ostream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc \ + /usr/include/c++/4.7/bits/ostream.tcc /usr/include/c++/4.7/istream \ + /usr/include/c++/4.7/bits/istream.tcc /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm.h zm_config.h ../config.h \ + zm_config_defines.h zm_logger.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_detector.h /usr/include/syslog.h \ + /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_image.h zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: diff --git a/src/.deps/zm_jpeg.Po b/src/.deps/zm_jpeg.Po new file mode 100644 index 000000000..6baed7c19 --- /dev/null +++ b/src/.deps/zm_jpeg.Po @@ -0,0 +1,295 @@ +zm_jpeg.o: zm_jpeg.cpp zm_jpeg.h /usr/include/setjmp.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/wchar.h /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_logger.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h + +zm_jpeg.h: + +/usr/include/setjmp.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/stdio.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: diff --git a/src/.deps/zm_local_camera.Po b/src/.deps/zm_local_camera.Po new file mode 100644 index 000000000..272154c08 --- /dev/null +++ b/src/.deps/zm_local_camera.Po @@ -0,0 +1,563 @@ +zm_local_camera.o: zm_local_camera.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_local_camera.h zm_camera.h /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h /usr/include/linux/videodev2.h \ + /usr/include/linux/types.h /usr/include/x86_64-linux-gnu/asm/types.h \ + /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ + /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ + /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ + /usr/include/linux/stddef.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types_64.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/sys/mman.h \ + /usr/include/x86_64-linux-gnu/bits/mman.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_local_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +/usr/include/linux/videodev2.h: + +/usr/include/linux/types.h: + +/usr/include/x86_64-linux-gnu/asm/types.h: + +/usr/include/asm-generic/types.h: + +/usr/include/asm-generic/int-ll64.h: + +/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: + +/usr/include/asm-generic/bitsperlong.h: + +/usr/include/linux/posix_types.h: + +/usr/include/linux/stddef.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/sys/mman.h: + +/usr/include/x86_64-linux-gnu/bits/mman.h: diff --git a/src/.deps/zm_logger.Po b/src/.deps/zm_logger.Po new file mode 100644 index 000000000..015a50955 --- /dev/null +++ b/src/.deps/zm_logger.Po @@ -0,0 +1,370 @@ +zm_logger.o: zm_logger.cpp zm_logger.h /usr/include/unistd.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/xlocale.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h zm_config.h \ + ../config.h zm_config_defines.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/syslog.h \ + /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/syscall.h \ + /usr/include/x86_64-linux-gnu/sys/syscall.h \ + /usr/include/x86_64-linux-gnu/asm/unistd.h \ + /usr/include/x86_64-linux-gnu/asm/unistd_64.h \ + /usr/include/x86_64-linux-gnu/bits/syscall.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/syscall.h: + +/usr/include/x86_64-linux-gnu/sys/syscall.h: + +/usr/include/x86_64-linux-gnu/asm/unistd.h: + +/usr/include/x86_64-linux-gnu/asm/unistd_64.h: + +/usr/include/x86_64-linux-gnu/bits/syscall.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: diff --git a/src/.deps/zm_monitor.Po b/src/.deps/zm_monitor.Po new file mode 100644 index 000000000..f5109b778 --- /dev/null +++ b/src/.deps/zm_monitor.Po @@ -0,0 +1,813 @@ +zm_monitor.o: zm_monitor.cpp /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/arpa/inet.h \ + /usr/include/netinet/in.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/glob.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h zm_db.h \ + zm_time.h /usr/include/x86_64-linux-gnu/sys/time.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/errno.h /usr/include/x86_64-linux-gnu/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + zm_monitor.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h zm_poly.h \ + zm_mem_utils.h zm_utils.h /usr/include/zlib.h /usr/include/zconf.h \ + zm_zone.h zm_event.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h zm_local_camera.h \ + /usr/include/linux/videodev2.h /usr/include/linux/types.h \ + /usr/include/x86_64-linux-gnu/asm/types.h \ + /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ + /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ + /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ + /usr/include/linux/stddef.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types_64.h zm_remote_camera.h \ + /usr/include/netdb.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h zm_remote_camera_http.h \ + zm_buffer.h zm_regexp.h /usr/include/pcre.h zm_remote_camera_rtsp.h \ + zm_rtsp.h zm_comms.h zm_exception.h zm_thread.h zm_rtp_source.h \ + zm_file_camera.h zm_ffmpeg_camera.h \ + /usr/include/x86_64-linux-gnu/sys/mman.h \ + /usr/include/x86_64-linux-gnu/bits/mman.h /usr/include/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/fcntl.h + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/arpa/inet.h: + +/usr/include/netinet/in.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/glob.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +zm_db.h: + +zm_time.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: + +zm_local_camera.h: + +/usr/include/linux/videodev2.h: + +/usr/include/linux/types.h: + +/usr/include/x86_64-linux-gnu/asm/types.h: + +/usr/include/asm-generic/types.h: + +/usr/include/asm-generic/int-ll64.h: + +/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: + +/usr/include/asm-generic/bitsperlong.h: + +/usr/include/linux/posix_types.h: + +/usr/include/linux/stddef.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: + +zm_remote_camera.h: + +/usr/include/netdb.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +zm_remote_camera_http.h: + +zm_buffer.h: + +zm_regexp.h: + +/usr/include/pcre.h: + +zm_remote_camera_rtsp.h: + +zm_rtsp.h: + +zm_comms.h: + +zm_exception.h: + +zm_thread.h: + +zm_rtp_source.h: + +zm_file_camera.h: + +zm_ffmpeg_camera.h: + +/usr/include/x86_64-linux-gnu/sys/mman.h: + +/usr/include/x86_64-linux-gnu/bits/mman.h: + +/usr/include/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/fcntl.h: diff --git a/src/.deps/zm_mpeg.Po b/src/.deps/zm_mpeg.Po new file mode 100644 index 000000000..26750ac9d --- /dev/null +++ b/src/.deps/zm_mpeg.Po @@ -0,0 +1,430 @@ +zm_mpeg.o: zm_mpeg.cpp /usr/include/stdlib.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/string.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_rgb.h zm_mpeg.h zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h + +/usr/include/stdlib.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_rgb.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: diff --git a/src/.deps/zm_plugin.Po b/src/.deps/zm_plugin.Po new file mode 100644 index 000000000..2a1b5978a --- /dev/null +++ b/src/.deps/zm_plugin.Po @@ -0,0 +1,298 @@ +zm_plugin.o: zm_plugin.cpp zm_plugin.h /usr/include/stdlib.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/stdio.h /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/wchar.h /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h \ + /usr/include/c++/4.7/stdexcept /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/string /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm.h zm_config.h ../config.h \ + zm_config_defines.h zm_logger.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h + +zm_plugin.h: + +/usr/include/stdlib.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/stdio.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: diff --git a/src/.deps/zm_plugin_manager.Po b/src/.deps/zm_plugin_manager.Po new file mode 100644 index 000000000..5c93a9603 --- /dev/null +++ b/src/.deps/zm_plugin_manager.Po @@ -0,0 +1,655 @@ +zm_plugin_manager.o: zm_plugin_manager.cpp zm_plugin_manager.h \ + /usr/include/stdio.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h /usr/include/x86_64-linux-gnu/sys/param.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/linux/param.h /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h zm.h \ + zm_config.h ../config.h zm_config_defines.h zm_logger.h \ + /usr/include/mysql/mysql.h /usr/include/mysql/mysql_version.h \ + /usr/include/mysql/mysql_com.h /usr/include/mysql/mysql_time.h \ + /usr/include/mysql/my_list.h /usr/include/mysql/typelib.h \ + /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_image_analyser.h /usr/include/c++/4.7/list \ + /usr/include/c++/4.7/bits/stl_list.h /usr/include/c++/4.7/bits/list.tcc \ + /usr/include/c++/4.7/stdexcept /usr/include/c++/4.7/iostream \ + /usr/include/c++/4.7/ostream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc \ + /usr/include/c++/4.7/bits/ostream.tcc /usr/include/c++/4.7/istream \ + /usr/include/c++/4.7/bits/istream.tcc /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_image.h zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +zm_plugin_manager.h: + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +zm_logger.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zm_poly.Po b/src/.deps/zm_poly.Po new file mode 100644 index 000000000..7a39ab09f --- /dev/null +++ b/src/.deps/zm_poly.Po @@ -0,0 +1,299 @@ +zm_poly.o: zm_poly.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_poly.h zm_coord.h zm_box.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_poly.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: diff --git a/src/.deps/zm_regexp.Po b/src/.deps/zm_regexp.Po new file mode 100644 index 000000000..32df8b282 --- /dev/null +++ b/src/.deps/zm_regexp.Po @@ -0,0 +1,287 @@ +zm_regexp.o: zm_regexp.cpp /usr/include/string.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_regexp.h /usr/include/pcre.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h + +/usr/include/string.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_regexp.h: + +/usr/include/pcre.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: diff --git a/src/.deps/zm_remote_camera.Po b/src/.deps/zm_remote_camera.Po new file mode 100644 index 000000000..c11683838 --- /dev/null +++ b/src/.deps/zm_remote_camera.Po @@ -0,0 +1,463 @@ +zm_remote_camera.o: zm_remote_camera.cpp zm_remote_camera.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/xlocale.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h /usr/include/netdb.h \ + /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h + +zm_remote_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: diff --git a/src/.deps/zm_remote_camera_http.Po b/src/.deps/zm_remote_camera_http.Po new file mode 100644 index 000000000..acb25bffe --- /dev/null +++ b/src/.deps/zm_remote_camera_http.Po @@ -0,0 +1,473 @@ +zm_remote_camera_http.o: zm_remote_camera_http.cpp \ + zm_remote_camera_http.h zm_remote_camera.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/time.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/xlocale.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_jpeg.h /usr/include/setjmp.h jinclude.h \ + /root/zm/libjpeg-turbo-1.2.1/jconfig.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h /usr/include/netdb.h \ + /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h zm_buffer.h zm_regexp.h \ + /usr/include/pcre.h + +zm_remote_camera_http.h: + +zm_remote_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/time.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +zm_buffer.h: + +zm_regexp.h: + +/usr/include/pcre.h: diff --git a/src/.deps/zm_remote_camera_rtsp.Po b/src/.deps/zm_remote_camera_rtsp.Po new file mode 100644 index 000000000..dcf666cd4 --- /dev/null +++ b/src/.deps/zm_remote_camera_rtsp.Po @@ -0,0 +1,582 @@ +zm_remote_camera_rtsp.o: zm_remote_camera_rtsp.cpp zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_remote_camera_rtsp.h zm_remote_camera.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_coord.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h /usr/include/netdb.h \ + /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h zm_buffer.h zm_rtsp.h \ + zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_comms.h zm_exception.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_thread.h zm_rtp_source.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_remote_camera_rtsp.h: + +zm_remote_camera.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_coord.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +zm_buffer.h: + +zm_rtsp.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_comms.h: + +zm_exception.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_thread.h: + +zm_rtp_source.h: diff --git a/src/.deps/zm_rtp.Po b/src/.deps/zm_rtp.Po new file mode 100644 index 000000000..764741cb4 --- /dev/null +++ b/src/.deps/zm_rtp.Po @@ -0,0 +1,271 @@ +zm_rtp.o: zm_rtp.cpp zm_rtp.h zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h + +zm_rtp.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: diff --git a/src/.deps/zm_rtp_ctrl.Po b/src/.deps/zm_rtp_ctrl.Po new file mode 100644 index 000000000..d500e3568 --- /dev/null +++ b/src/.deps/zm_rtp_ctrl.Po @@ -0,0 +1,521 @@ +zm_rtp_ctrl.o: zm_rtp_ctrl.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_rtp_ctrl.h zm_rtp.h zm_comms.h zm_exception.h /usr/include/netdb.h \ + /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/string.h \ + /usr/include/c++/4.7/set /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc zm_thread.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h zm_time.h zm_rtsp.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_rtp_source.h zm_buffer.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_rtp_ctrl.h: + +zm_rtp.h: + +zm_comms.h: + +zm_exception.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/string.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +zm_thread.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +zm_time.h: + +zm_rtsp.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_rtp_source.h: + +zm_buffer.h: diff --git a/src/.deps/zm_rtp_data.Po b/src/.deps/zm_rtp_data.Po new file mode 100644 index 000000000..99ce87dec --- /dev/null +++ b/src/.deps/zm_rtp_data.Po @@ -0,0 +1,521 @@ +zm_rtp_data.o: zm_rtp_data.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_rtp_data.h zm_thread.h zm_exception.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc zm_buffer.h /usr/include/string.h \ + zm_rtsp.h zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_comms.h /usr/include/netdb.h \ + /usr/include/netinet/in.h /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_rtp_source.h \ + /usr/include/arpa/inet.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_rtp_data.h: + +zm_thread.h: + +zm_exception.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +zm_buffer.h: + +/usr/include/string.h: + +zm_rtsp.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_comms.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_rtp_source.h: + +/usr/include/arpa/inet.h: diff --git a/src/.deps/zm_rtp_source.Po b/src/.deps/zm_rtp_source.Po new file mode 100644 index 000000000..60fae6d12 --- /dev/null +++ b/src/.deps/zm_rtp_source.Po @@ -0,0 +1,344 @@ +zm_rtp_source.o: zm_rtp_source.cpp zm_rtp_source.h zm_buffer.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + /usr/include/string.h zm_thread.h zm_exception.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc zm_time.h zm_rtp_data.h \ + /usr/include/arpa/inet.h /usr/include/netinet/in.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h + +zm_rtp_source.h: + +zm_buffer.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/string.h: + +zm_thread.h: + +zm_exception.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +zm_time.h: + +zm_rtp_data.h: + +/usr/include/arpa/inet.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: diff --git a/src/.deps/zm_rtsp.Po b/src/.deps/zm_rtsp.Po new file mode 100644 index 000000000..c3688b036 --- /dev/null +++ b/src/.deps/zm_rtsp.Po @@ -0,0 +1,547 @@ +zm_rtsp.o: zm_rtsp.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_rtsp.h zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_comms.h zm_exception.h \ + /usr/include/netdb.h /usr/include/netinet/in.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/bits/in.h /usr/include/rpc/netdb.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/netdb.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc zm_thread.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h zm_rtp_source.h zm_buffer.h \ + zm_rtp_data.h zm_rtp_ctrl.h zm_rtp.h zm_db.h zm_sdp.h \ + /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_rtsp.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_comms.h: + +zm_exception.h: + +/usr/include/netdb.h: + +/usr/include/netinet/in.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/bits/in.h: + +/usr/include/rpc/netdb.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/netdb.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +zm_thread.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +zm_rtp_source.h: + +zm_buffer.h: + +zm_rtp_data.h: + +zm_rtp_ctrl.h: + +zm_rtp.h: + +zm_db.h: + +zm_sdp.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: diff --git a/src/.deps/zm_sdp.Po b/src/.deps/zm_sdp.Po new file mode 100644 index 000000000..0fa6d7d38 --- /dev/null +++ b/src/.deps/zm_sdp.Po @@ -0,0 +1,453 @@ +zm_sdp.o: zm_sdp.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_sdp.h zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc zm_exception.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/errno.h /usr/include/x86_64-linux-gnu/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_sdp.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +zm_exception.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: diff --git a/src/.deps/zm_signal.Po b/src/.deps/zm_signal.Po new file mode 100644 index 000000000..81f6b5829 --- /dev/null +++ b/src/.deps/zm_signal.Po @@ -0,0 +1,320 @@ +zm_signal.o: zm_signal.cpp zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: diff --git a/src/.deps/zm_stream.Po b/src/.deps/zm_stream.Po new file mode 100644 index 000000000..863661909 --- /dev/null +++ b/src/.deps/zm_stream.Po @@ -0,0 +1,692 @@ +zm_stream.o: zm_stream.cpp /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h /usr/include/string.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_mpeg.h zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/inttypes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h /usr/include/math.h \ + /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h /usr/include/libio.h \ + /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_monitor.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h zm_poly.h \ + zm_mem_utils.h zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/string.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/inttypes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zm_thread.Po b/src/.deps/zm_thread.Po new file mode 100644 index 000000000..8a5431b07 --- /dev/null +++ b/src/.deps/zm_thread.Po @@ -0,0 +1,341 @@ +zm_thread.o: zm_thread.cpp zm_thread.h /usr/include/unistd.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/pthread.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h zm_exception.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/string.h \ + /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + zm_threaddata.cpp + +zm_thread.h: + +/usr/include/unistd.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/pthread.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +zm_exception.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/string.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +zm_threaddata.cpp: diff --git a/src/.deps/zm_time.Po b/src/.deps/zm_time.Po new file mode 100644 index 000000000..256f73978 --- /dev/null +++ b/src/.deps/zm_time.Po @@ -0,0 +1,274 @@ +zm_time.o: zm_time.cpp zm_time.h zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + /usr/include/x86_64-linux-gnu/sys/time.h + +zm_time.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: diff --git a/src/.deps/zm_timer.Po b/src/.deps/zm_timer.Po new file mode 100644 index 000000000..46f7e6e91 --- /dev/null +++ b/src/.deps/zm_timer.Po @@ -0,0 +1,300 @@ +zm_timer.o: zm_timer.cpp zm_timer.h zm_thread.h /usr/include/unistd.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/pthread.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/sched.h \ + /usr/include/time.h /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h zm_exception.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc + +zm_timer.h: + +zm_thread.h: + +/usr/include/unistd.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/pthread.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +zm_exception.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: diff --git a/src/.deps/zm_user.Po b/src/.deps/zm_user.Po new file mode 100644 index 000000000..c04ac182e --- /dev/null +++ b/src/.deps/zm_user.Po @@ -0,0 +1,342 @@ +zm_user.o: zm_user.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_user.h /usr/include/gnutls/openssl.h \ + /usr/include/gnutls/gnutls.h /usr/include/gnutls/compat.h \ + /usr/include/gcrypt.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/gpg-error.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/gcrypt-module.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_user.h: + +/usr/include/gnutls/openssl.h: + +/usr/include/gnutls/gnutls.h: + +/usr/include/gnutls/compat.h: + +/usr/include/gcrypt.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/gpg-error.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/gcrypt-module.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: diff --git a/src/.deps/zm_utils.Po b/src/.deps/zm_utils.Po new file mode 100644 index 000000000..3d4ce2c45 --- /dev/null +++ b/src/.deps/zm_utils.Po @@ -0,0 +1,307 @@ +zm_utils.o: zm_utils.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/string.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/string.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: diff --git a/src/.deps/zm_zone.Po b/src/.deps/zm_zone.Po new file mode 100644 index 000000000..80a119ab8 --- /dev/null +++ b/src/.deps/zm_zone.Po @@ -0,0 +1,693 @@ +zm_zone.o: zm_zone.cpp zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/xlocale.h /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_zone.h zm_rgb.h zm_coord.h zm_poly.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_mem_utils.h zm_utils.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_monitor.h \ + /usr/include/c++/4.7/sstream /usr/include/c++/4.7/istream \ + /usr/include/c++/4.7/ios /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_zone.h: + +zm_rgb.h: + +zm_coord.h: + +zm_poly.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_monitor.h: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zma.Po b/src/.deps/zma.Po new file mode 100644 index 000000000..6c508ba1c --- /dev/null +++ b/src/.deps/zma.Po @@ -0,0 +1,718 @@ +zma.o: zma.cpp /usr/include/getopt.h /usr/include/ctype.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_signal.h /usr/include/execinfo.h zm_monitor.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +/usr/include/getopt.h: + +/usr/include/ctype.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_signal.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zmc.Po b/src/.deps/zmc.Po new file mode 100644 index 000000000..311cdfb36 --- /dev/null +++ b/src/.deps/zmc.Po @@ -0,0 +1,726 @@ +zmc.o: zmc.cpp /usr/include/getopt.h /usr/include/ctype.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/values.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/float.h zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_time.h /usr/include/x86_64-linux-gnu/sys/time.h zm_signal.h \ + /usr/include/execinfo.h zm_monitor.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/stdlib.h /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/string.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +/usr/include/getopt.h: + +/usr/include/ctype.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/values.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/float.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_time.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +zm_signal.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/string.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zmf.Po b/src/.deps/zmf.Po new file mode 100644 index 000000000..cc2a60300 --- /dev/null +++ b/src/.deps/zmf.Po @@ -0,0 +1,722 @@ +zmf.o: zmf.cpp /usr/include/stdio.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/sys/un.h /usr/include/string.h \ + /usr/include/signal.h /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h zm.h zm_config.h \ + ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_signal.h /usr/include/execinfo.h zm_monitor.h \ + /usr/include/c++/4.7/vector /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h zm_mpeg.h \ + zm_ffmpeg.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/common.h /usr/include/inttypes.h \ + /usr/include/libavutil/attributes.h /usr/include/libavutil/avconfig.h \ + /usr/include/libavutil/mem.h /usr/include/libavutil/error.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/mathematics.h \ + /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h zmf.h + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +/usr/include/string.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_signal.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: + +zmf.h: diff --git a/src/.deps/zmfix.Po b/src/.deps/zmfix.Po new file mode 100644 index 000000000..28075c479 --- /dev/null +++ b/src/.deps/zmfix.Po @@ -0,0 +1,347 @@ +zmfix.o: zmfix.cpp /usr/include/stdio.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/unistd.h \ + /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/errno.h /usr/include/x86_64-linux-gnu/bits/errno.h \ + /usr/include/linux/errno.h /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/fcntl.h /usr/include/x86_64-linux-gnu/bits/fcntl.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/fcntl.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: diff --git a/src/.deps/zms.Po b/src/.deps/zms.Po new file mode 100644 index 000000000..7d3f75494 --- /dev/null +++ b/src/.deps/zms.Po @@ -0,0 +1,754 @@ +zms.o: zms.cpp /usr/include/x86_64-linux-gnu/sys/ipc.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/ipctypes.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h \ + /usr/include/x86_64-linux-gnu/bits/ipc.h \ + /usr/include/x86_64-linux-gnu/sys/msg.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/msq.h /usr/include/time.h zm.h \ + zm_config.h ../config.h zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h /usr/include/xlocale.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_user.h /usr/include/gnutls/openssl.h \ + /usr/include/gnutls/gnutls.h /usr/include/gnutls/compat.h \ + /usr/include/gcrypt.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/gpg-error.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/gcrypt-module.h \ + zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + zm_monitor.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +/usr/include/x86_64-linux-gnu/sys/ipc.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/ipctypes.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/x86_64-linux-gnu/bits/ipc.h: + +/usr/include/x86_64-linux-gnu/sys/msg.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/msq.h: + +/usr/include/time.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/xlocale.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_user.h: + +/usr/include/gnutls/openssl.h: + +/usr/include/gnutls/gnutls.h: + +/usr/include/gnutls/compat.h: + +/usr/include/gcrypt.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/gpg-error.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/gcrypt-module.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zmstreamer.Po b/src/.deps/zmstreamer.Po new file mode 100644 index 000000000..0d72970cf --- /dev/null +++ b/src/.deps/zmstreamer.Po @@ -0,0 +1,753 @@ +zmstreamer.o: zmstreamer.cpp /usr/include/stdio.h /usr/include/features.h \ + /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + /usr/include/x86_64-linux-gnu/sys/types.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h /usr/include/alloca.h \ + /usr/include/x86_64-linux-gnu/sys/ipc.h \ + /usr/include/x86_64-linux-gnu/bits/ipctypes.h \ + /usr/include/x86_64-linux-gnu/bits/ipc.h \ + /usr/include/x86_64-linux-gnu/sys/msg.h \ + /usr/include/x86_64-linux-gnu/bits/msq.h zm.h zm_config.h ../config.h \ + zm_config_defines.h /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/ctype.h \ + /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/getopt.h \ + /usr/include/c++/4.7/map /usr/include/c++/4.7/bits/stl_tree.h \ + /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_user.h /usr/include/gnutls/openssl.h \ + /usr/include/gnutls/gnutls.h /usr/include/gnutls/compat.h \ + /usr/include/gcrypt.h /usr/include/string.h /usr/include/gpg-error.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/gcrypt-module.h \ + zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + zm_monitor.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h + +/usr/include/stdio.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/alloca.h: + +/usr/include/x86_64-linux-gnu/sys/ipc.h: + +/usr/include/x86_64-linux-gnu/bits/ipctypes.h: + +/usr/include/x86_64-linux-gnu/bits/ipc.h: + +/usr/include/x86_64-linux-gnu/sys/msg.h: + +/usr/include/x86_64-linux-gnu/bits/msq.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/ctype.h: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/getopt.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_user.h: + +/usr/include/gnutls/openssl.h: + +/usr/include/gnutls/gnutls.h: + +/usr/include/gnutls/compat.h: + +/usr/include/gcrypt.h: + +/usr/include/string.h: + +/usr/include/gpg-error.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/gcrypt-module.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: diff --git a/src/.deps/zmu.Po b/src/.deps/zmu.Po new file mode 100644 index 000000000..9608d5ee1 --- /dev/null +++ b/src/.deps/zmu.Po @@ -0,0 +1,771 @@ +zmu.o: zmu.cpp /usr/include/getopt.h /usr/include/ctype.h \ + /usr/include/features.h /usr/include/x86_64-linux-gnu/bits/predefs.h \ + /usr/include/x86_64-linux-gnu/sys/cdefs.h \ + /usr/include/x86_64-linux-gnu/bits/wordsize.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs.h \ + /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \ + /usr/include/x86_64-linux-gnu/bits/types.h \ + /usr/include/x86_64-linux-gnu/bits/typesizes.h /usr/include/endian.h \ + /usr/include/x86_64-linux-gnu/bits/endian.h \ + /usr/include/x86_64-linux-gnu/bits/byteswap.h /usr/include/xlocale.h \ + zm.h zm_config.h ../config.h zm_config_defines.h \ + /usr/include/c++/4.7/string \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h \ + /usr/include/c++/4.7/bits/stringfwd.h \ + /usr/include/c++/4.7/bits/char_traits.h \ + /usr/include/c++/4.7/bits/stl_algobase.h \ + /usr/include/c++/4.7/bits/functexcept.h \ + /usr/include/c++/4.7/bits/exception_defines.h \ + /usr/include/c++/4.7/bits/cpp_type_traits.h \ + /usr/include/c++/4.7/ext/type_traits.h \ + /usr/include/c++/4.7/ext/numeric_traits.h \ + /usr/include/c++/4.7/bits/stl_pair.h /usr/include/c++/4.7/bits/move.h \ + /usr/include/c++/4.7/bits/concept_check.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_types.h \ + /usr/include/c++/4.7/bits/stl_iterator_base_funcs.h \ + /usr/include/c++/4.7/bits/stl_iterator.h \ + /usr/include/c++/4.7/debug/debug.h /usr/include/c++/4.7/bits/postypes.h \ + /usr/include/c++/4.7/cwchar /usr/include/wchar.h /usr/include/stdio.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h \ + /usr/include/x86_64-linux-gnu/bits/wchar.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h \ + /usr/include/c++/4.7/bits/allocator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h \ + /usr/include/c++/4.7/ext/new_allocator.h /usr/include/c++/4.7/new \ + /usr/include/c++/4.7/exception \ + /usr/include/c++/4.7/bits/atomic_lockfree_defines.h \ + /usr/include/c++/4.7/bits/localefwd.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h \ + /usr/include/c++/4.7/clocale /usr/include/locale.h \ + /usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/c++/4.7/iosfwd \ + /usr/include/c++/4.7/cctype /usr/include/c++/4.7/bits/ostream_insert.h \ + /usr/include/c++/4.7/bits/cxxabi_forced.h \ + /usr/include/c++/4.7/bits/stl_function.h \ + /usr/include/c++/4.7/backward/binders.h \ + /usr/include/c++/4.7/bits/range_access.h \ + /usr/include/c++/4.7/bits/basic_string.h \ + /usr/include/c++/4.7/ext/atomicity.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h \ + /usr/include/pthread.h /usr/include/sched.h /usr/include/time.h \ + /usr/include/x86_64-linux-gnu/bits/sched.h \ + /usr/include/x86_64-linux-gnu/bits/time.h \ + /usr/include/x86_64-linux-gnu/bits/pthreadtypes.h \ + /usr/include/x86_64-linux-gnu/bits/setjmp.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h \ + /usr/include/c++/4.7/bits/basic_string.tcc zm_logger.h \ + /usr/include/unistd.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h \ + /usr/include/x86_64-linux-gnu/bits/environments.h \ + /usr/include/x86_64-linux-gnu/bits/confname.h /usr/include/c++/4.7/map \ + /usr/include/c++/4.7/bits/stl_tree.h /usr/include/c++/4.7/bits/stl_map.h \ + /usr/include/c++/4.7/bits/stl_multimap.h /usr/include/mysql/mysql.h \ + /usr/include/x86_64-linux-gnu/sys/types.h \ + /usr/include/x86_64-linux-gnu/sys/select.h \ + /usr/include/x86_64-linux-gnu/bits/select.h \ + /usr/include/x86_64-linux-gnu/bits/sigset.h \ + /usr/include/x86_64-linux-gnu/sys/sysmacros.h \ + /usr/include/mysql/mysql_version.h /usr/include/mysql/mysql_com.h \ + /usr/include/mysql/mysql_time.h /usr/include/mysql/my_list.h \ + /usr/include/mysql/typelib.h /usr/include/mysql/my_alloc.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h /usr/include/stdint.h \ + zm_db.h zm_user.h /usr/include/gnutls/openssl.h \ + /usr/include/gnutls/gnutls.h /usr/include/gnutls/compat.h \ + /usr/include/gcrypt.h /usr/include/stdlib.h \ + /usr/include/x86_64-linux-gnu/bits/waitflags.h \ + /usr/include/x86_64-linux-gnu/bits/waitstatus.h /usr/include/alloca.h \ + /usr/include/string.h /usr/include/gpg-error.h \ + /usr/include/x86_64-linux-gnu/sys/socket.h \ + /usr/include/x86_64-linux-gnu/sys/uio.h \ + /usr/include/x86_64-linux-gnu/bits/uio.h \ + /usr/include/x86_64-linux-gnu/bits/socket.h \ + /usr/include/x86_64-linux-gnu/bits/sockaddr.h \ + /usr/include/x86_64-linux-gnu/asm/socket.h \ + /usr/include/asm-generic/socket.h \ + /usr/include/x86_64-linux-gnu/asm/sockios.h \ + /usr/include/asm-generic/sockios.h \ + /usr/include/x86_64-linux-gnu/sys/time.h /usr/include/gcrypt-module.h \ + zm_signal.h /usr/include/signal.h \ + /usr/include/x86_64-linux-gnu/bits/signum.h \ + /usr/include/x86_64-linux-gnu/bits/siginfo.h \ + /usr/include/x86_64-linux-gnu/bits/sigaction.h \ + /usr/include/x86_64-linux-gnu/bits/sigcontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigstack.h \ + /usr/include/x86_64-linux-gnu/sys/ucontext.h \ + /usr/include/x86_64-linux-gnu/bits/sigthread.h /usr/include/execinfo.h \ + zm_monitor.h /usr/include/c++/4.7/vector \ + /usr/include/c++/4.7/bits/stl_construct.h \ + /usr/include/c++/4.7/ext/alloc_traits.h \ + /usr/include/c++/4.7/bits/stl_uninitialized.h \ + /usr/include/c++/4.7/bits/stl_vector.h \ + /usr/include/c++/4.7/bits/stl_bvector.h \ + /usr/include/c++/4.7/bits/vector.tcc /usr/include/c++/4.7/sstream \ + /usr/include/c++/4.7/istream /usr/include/c++/4.7/ios \ + /usr/include/c++/4.7/bits/ios_base.h \ + /usr/include/c++/4.7/bits/locale_classes.h \ + /usr/include/c++/4.7/bits/locale_classes.tcc \ + /usr/include/c++/4.7/streambuf /usr/include/c++/4.7/bits/streambuf.tcc \ + /usr/include/c++/4.7/bits/basic_ios.h \ + /usr/include/c++/4.7/bits/locale_facets.h /usr/include/c++/4.7/cwctype \ + /usr/include/wctype.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h \ + /usr/include/c++/4.7/bits/streambuf_iterator.h \ + /usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h \ + /usr/include/c++/4.7/bits/locale_facets.tcc \ + /usr/include/c++/4.7/bits/basic_ios.tcc /usr/include/c++/4.7/ostream \ + /usr/include/c++/4.7/bits/ostream.tcc \ + /usr/include/c++/4.7/bits/istream.tcc \ + /usr/include/c++/4.7/bits/sstream.tcc zm_coord.h zm_image.h zm_jpeg.h \ + /usr/include/setjmp.h jinclude.h /root/zm/libjpeg-turbo-1.2.1/jconfig.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \ + /usr/include/x86_64-linux-gnu/bits/sys_errlist.h \ + /root/zm/libjpeg-turbo-1.2.1/jpeglib.h \ + /root/zm/libjpeg-turbo-1.2.1/jmorecfg.h \ + /root/zm/libjpeg-turbo-1.2.1/jerror.h zm_rgb.h zm_box.h \ + /usr/include/math.h /usr/include/x86_64-linux-gnu/bits/huge_val.h \ + /usr/include/x86_64-linux-gnu/bits/huge_valf.h \ + /usr/include/x86_64-linux-gnu/bits/huge_vall.h \ + /usr/include/x86_64-linux-gnu/bits/inf.h \ + /usr/include/x86_64-linux-gnu/bits/nan.h \ + /usr/include/x86_64-linux-gnu/bits/mathdef.h \ + /usr/include/x86_64-linux-gnu/bits/mathcalls.h zm_poly.h zm_mem_utils.h \ + zm_utils.h /usr/include/errno.h \ + /usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/linux/errno.h \ + /usr/include/x86_64-linux-gnu/asm/errno.h \ + /usr/include/asm-generic/errno.h /usr/include/asm-generic/errno-base.h \ + /usr/include/zlib.h /usr/include/zconf.h zm_zone.h zm_event.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h \ + /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h \ + /usr/include/limits.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ + /usr/include/x86_64-linux-gnu/bits/local_lim.h \ + /usr/include/linux/limits.h \ + /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ + /usr/include/x86_64-linux-gnu/bits/xopen_lim.h \ + /usr/include/x86_64-linux-gnu/sys/stat.h \ + /usr/include/x86_64-linux-gnu/bits/stat.h /usr/include/c++/4.7/set \ + /usr/include/c++/4.7/bits/stl_set.h \ + /usr/include/c++/4.7/bits/stl_multiset.h zm_stream.h \ + /usr/include/x86_64-linux-gnu/sys/un.h zm_mpeg.h zm_ffmpeg.h \ + /usr/include/libavutil/avutil.h /usr/include/libavutil/common.h \ + /usr/include/inttypes.h /usr/include/libavutil/attributes.h \ + /usr/include/libavutil/avconfig.h /usr/include/libavutil/mem.h \ + /usr/include/libavutil/error.h /usr/include/libavutil/avutil.h \ + /usr/include/libavutil/mathematics.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/intfloat_readwrite.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavcodec/avcodec.h \ + /usr/include/libavutil/samplefmt.h /usr/include/libavutil/cpu.h \ + /usr/include/libavutil/dict.h /usr/include/libavutil/log.h \ + /usr/include/libavutil/pixfmt.h /usr/include/libavutil/rational.h \ + /usr/include/libavutil/audioconvert.h /usr/include/libavcodec/version.h \ + /usr/include/libavformat/avformat.h /usr/include/libavformat/avio.h \ + /usr/include/libavutil/common.h /usr/include/libavformat/version.h \ + /usr/include/libswscale/swscale.h zm_camera.h \ + /usr/include/x86_64-linux-gnu/sys/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctls.h \ + /usr/include/x86_64-linux-gnu/asm/ioctls.h \ + /usr/include/asm-generic/ioctls.h /usr/include/linux/ioctl.h \ + /usr/include/x86_64-linux-gnu/asm/ioctl.h \ + /usr/include/asm-generic/ioctl.h \ + /usr/include/x86_64-linux-gnu/bits/ioctl-types.h \ + /usr/include/x86_64-linux-gnu/sys/ttydefaults.h zm_plugin_manager.h \ + /usr/include/x86_64-linux-gnu/sys/dir.h /usr/include/dirent.h \ + /usr/include/x86_64-linux-gnu/bits/dirent.h \ + /usr/include/x86_64-linux-gnu/sys/param.h /usr/include/linux/param.h \ + /usr/include/x86_64-linux-gnu/asm/param.h \ + /usr/include/asm-generic/param.h zm_image_analyser.h \ + /usr/include/c++/4.7/list /usr/include/c++/4.7/bits/stl_list.h \ + /usr/include/c++/4.7/bits/list.tcc /usr/include/c++/4.7/stdexcept \ + /usr/include/c++/4.7/iostream /usr/include/c++/4.7/memory \ + /usr/include/c++/4.7/bits/stl_tempbuf.h \ + /usr/include/c++/4.7/bits/stl_raw_storage_iter.h \ + /usr/include/c++/4.7/backward/auto_ptr.h zm_detector.h \ + /usr/include/syslog.h /usr/include/x86_64-linux-gnu/sys/syslog.h \ + /usr/include/x86_64-linux-gnu/bits/syslog-path.h /usr/include/libgen.h \ + zm_plugin.h /usr/include/dlfcn.h \ + /usr/include/x86_64-linux-gnu/bits/dlfcn.h zm_local_camera.h \ + /usr/include/linux/videodev2.h /usr/include/linux/types.h \ + /usr/include/x86_64-linux-gnu/asm/types.h \ + /usr/include/asm-generic/types.h /usr/include/asm-generic/int-ll64.h \ + /usr/include/x86_64-linux-gnu/asm/bitsperlong.h \ + /usr/include/asm-generic/bitsperlong.h /usr/include/linux/posix_types.h \ + /usr/include/linux/stddef.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types.h \ + /usr/include/x86_64-linux-gnu/asm/posix_types_64.h + +/usr/include/getopt.h: + +/usr/include/ctype.h: + +/usr/include/features.h: + +/usr/include/x86_64-linux-gnu/bits/predefs.h: + +/usr/include/x86_64-linux-gnu/sys/cdefs.h: + +/usr/include/x86_64-linux-gnu/bits/wordsize.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs.h: + +/usr/include/x86_64-linux-gnu/gnu/stubs-64.h: + +/usr/include/x86_64-linux-gnu/bits/types.h: + +/usr/include/x86_64-linux-gnu/bits/typesizes.h: + +/usr/include/endian.h: + +/usr/include/x86_64-linux-gnu/bits/endian.h: + +/usr/include/x86_64-linux-gnu/bits/byteswap.h: + +/usr/include/xlocale.h: + +zm.h: + +zm_config.h: + +../config.h: + +zm_config_defines.h: + +/usr/include/c++/4.7/string: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++config.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/os_defines.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/cpu_defines.h: + +/usr/include/c++/4.7/bits/stringfwd.h: + +/usr/include/c++/4.7/bits/char_traits.h: + +/usr/include/c++/4.7/bits/stl_algobase.h: + +/usr/include/c++/4.7/bits/functexcept.h: + +/usr/include/c++/4.7/bits/exception_defines.h: + +/usr/include/c++/4.7/bits/cpp_type_traits.h: + +/usr/include/c++/4.7/ext/type_traits.h: + +/usr/include/c++/4.7/ext/numeric_traits.h: + +/usr/include/c++/4.7/bits/stl_pair.h: + +/usr/include/c++/4.7/bits/move.h: + +/usr/include/c++/4.7/bits/concept_check.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_types.h: + +/usr/include/c++/4.7/bits/stl_iterator_base_funcs.h: + +/usr/include/c++/4.7/bits/stl_iterator.h: + +/usr/include/c++/4.7/debug/debug.h: + +/usr/include/c++/4.7/bits/postypes.h: + +/usr/include/c++/4.7/cwchar: + +/usr/include/wchar.h: + +/usr/include/stdio.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdarg.h: + +/usr/include/x86_64-linux-gnu/bits/wchar.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stddef.h: + +/usr/include/c++/4.7/bits/allocator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++allocator.h: + +/usr/include/c++/4.7/ext/new_allocator.h: + +/usr/include/c++/4.7/new: + +/usr/include/c++/4.7/exception: + +/usr/include/c++/4.7/bits/atomic_lockfree_defines.h: + +/usr/include/c++/4.7/bits/localefwd.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/c++locale.h: + +/usr/include/c++/4.7/clocale: + +/usr/include/locale.h: + +/usr/include/x86_64-linux-gnu/bits/locale.h: + +/usr/include/c++/4.7/iosfwd: + +/usr/include/c++/4.7/cctype: + +/usr/include/c++/4.7/bits/ostream_insert.h: + +/usr/include/c++/4.7/bits/cxxabi_forced.h: + +/usr/include/c++/4.7/bits/stl_function.h: + +/usr/include/c++/4.7/backward/binders.h: + +/usr/include/c++/4.7/bits/range_access.h: + +/usr/include/c++/4.7/bits/basic_string.h: + +/usr/include/c++/4.7/ext/atomicity.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/gthr-default.h: + +/usr/include/pthread.h: + +/usr/include/sched.h: + +/usr/include/time.h: + +/usr/include/x86_64-linux-gnu/bits/sched.h: + +/usr/include/x86_64-linux-gnu/bits/time.h: + +/usr/include/x86_64-linux-gnu/bits/pthreadtypes.h: + +/usr/include/x86_64-linux-gnu/bits/setjmp.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/atomic_word.h: + +/usr/include/c++/4.7/bits/basic_string.tcc: + +zm_logger.h: + +/usr/include/unistd.h: + +/usr/include/x86_64-linux-gnu/bits/posix_opt.h: + +/usr/include/x86_64-linux-gnu/bits/environments.h: + +/usr/include/x86_64-linux-gnu/bits/confname.h: + +/usr/include/c++/4.7/map: + +/usr/include/c++/4.7/bits/stl_tree.h: + +/usr/include/c++/4.7/bits/stl_map.h: + +/usr/include/c++/4.7/bits/stl_multimap.h: + +/usr/include/mysql/mysql.h: + +/usr/include/x86_64-linux-gnu/sys/types.h: + +/usr/include/x86_64-linux-gnu/sys/select.h: + +/usr/include/x86_64-linux-gnu/bits/select.h: + +/usr/include/x86_64-linux-gnu/bits/sigset.h: + +/usr/include/x86_64-linux-gnu/sys/sysmacros.h: + +/usr/include/mysql/mysql_version.h: + +/usr/include/mysql/mysql_com.h: + +/usr/include/mysql/mysql_time.h: + +/usr/include/mysql/my_list.h: + +/usr/include/mysql/typelib.h: + +/usr/include/mysql/my_alloc.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include/stdint.h: + +/usr/include/stdint.h: + +zm_db.h: + +zm_user.h: + +/usr/include/gnutls/openssl.h: + +/usr/include/gnutls/gnutls.h: + +/usr/include/gnutls/compat.h: + +/usr/include/gcrypt.h: + +/usr/include/stdlib.h: + +/usr/include/x86_64-linux-gnu/bits/waitflags.h: + +/usr/include/x86_64-linux-gnu/bits/waitstatus.h: + +/usr/include/alloca.h: + +/usr/include/string.h: + +/usr/include/gpg-error.h: + +/usr/include/x86_64-linux-gnu/sys/socket.h: + +/usr/include/x86_64-linux-gnu/sys/uio.h: + +/usr/include/x86_64-linux-gnu/bits/uio.h: + +/usr/include/x86_64-linux-gnu/bits/socket.h: + +/usr/include/x86_64-linux-gnu/bits/sockaddr.h: + +/usr/include/x86_64-linux-gnu/asm/socket.h: + +/usr/include/asm-generic/socket.h: + +/usr/include/x86_64-linux-gnu/asm/sockios.h: + +/usr/include/asm-generic/sockios.h: + +/usr/include/x86_64-linux-gnu/sys/time.h: + +/usr/include/gcrypt-module.h: + +zm_signal.h: + +/usr/include/signal.h: + +/usr/include/x86_64-linux-gnu/bits/signum.h: + +/usr/include/x86_64-linux-gnu/bits/siginfo.h: + +/usr/include/x86_64-linux-gnu/bits/sigaction.h: + +/usr/include/x86_64-linux-gnu/bits/sigcontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigstack.h: + +/usr/include/x86_64-linux-gnu/sys/ucontext.h: + +/usr/include/x86_64-linux-gnu/bits/sigthread.h: + +/usr/include/execinfo.h: + +zm_monitor.h: + +/usr/include/c++/4.7/vector: + +/usr/include/c++/4.7/bits/stl_construct.h: + +/usr/include/c++/4.7/ext/alloc_traits.h: + +/usr/include/c++/4.7/bits/stl_uninitialized.h: + +/usr/include/c++/4.7/bits/stl_vector.h: + +/usr/include/c++/4.7/bits/stl_bvector.h: + +/usr/include/c++/4.7/bits/vector.tcc: + +/usr/include/c++/4.7/sstream: + +/usr/include/c++/4.7/istream: + +/usr/include/c++/4.7/ios: + +/usr/include/c++/4.7/bits/ios_base.h: + +/usr/include/c++/4.7/bits/locale_classes.h: + +/usr/include/c++/4.7/bits/locale_classes.tcc: + +/usr/include/c++/4.7/streambuf: + +/usr/include/c++/4.7/bits/streambuf.tcc: + +/usr/include/c++/4.7/bits/basic_ios.h: + +/usr/include/c++/4.7/bits/locale_facets.h: + +/usr/include/c++/4.7/cwctype: + +/usr/include/wctype.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_base.h: + +/usr/include/c++/4.7/bits/streambuf_iterator.h: + +/usr/include/c++/4.7/x86_64-linux-gnu/bits/ctype_inline.h: + +/usr/include/c++/4.7/bits/locale_facets.tcc: + +/usr/include/c++/4.7/bits/basic_ios.tcc: + +/usr/include/c++/4.7/ostream: + +/usr/include/c++/4.7/bits/ostream.tcc: + +/usr/include/c++/4.7/bits/istream.tcc: + +/usr/include/c++/4.7/bits/sstream.tcc: + +zm_coord.h: + +zm_image.h: + +zm_jpeg.h: + +/usr/include/setjmp.h: + +jinclude.h: + +/root/zm/libjpeg-turbo-1.2.1/jconfig.h: + +/usr/include/libio.h: + +/usr/include/_G_config.h: + +/usr/include/x86_64-linux-gnu/bits/stdio_lim.h: + +/usr/include/x86_64-linux-gnu/bits/sys_errlist.h: + +/root/zm/libjpeg-turbo-1.2.1/jpeglib.h: + +/root/zm/libjpeg-turbo-1.2.1/jmorecfg.h: + +/root/zm/libjpeg-turbo-1.2.1/jerror.h: + +zm_rgb.h: + +zm_box.h: + +/usr/include/math.h: + +/usr/include/x86_64-linux-gnu/bits/huge_val.h: + +/usr/include/x86_64-linux-gnu/bits/huge_valf.h: + +/usr/include/x86_64-linux-gnu/bits/huge_vall.h: + +/usr/include/x86_64-linux-gnu/bits/inf.h: + +/usr/include/x86_64-linux-gnu/bits/nan.h: + +/usr/include/x86_64-linux-gnu/bits/mathdef.h: + +/usr/include/x86_64-linux-gnu/bits/mathcalls.h: + +zm_poly.h: + +zm_mem_utils.h: + +zm_utils.h: + +/usr/include/errno.h: + +/usr/include/x86_64-linux-gnu/bits/errno.h: + +/usr/include/linux/errno.h: + +/usr/include/x86_64-linux-gnu/asm/errno.h: + +/usr/include/asm-generic/errno.h: + +/usr/include/asm-generic/errno-base.h: + +/usr/include/zlib.h: + +/usr/include/zconf.h: + +zm_zone.h: + +zm_event.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/limits.h: + +/usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed/syslimits.h: + +/usr/include/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix1_lim.h: + +/usr/include/x86_64-linux-gnu/bits/local_lim.h: + +/usr/include/linux/limits.h: + +/usr/include/x86_64-linux-gnu/bits/posix2_lim.h: + +/usr/include/x86_64-linux-gnu/bits/xopen_lim.h: + +/usr/include/x86_64-linux-gnu/sys/stat.h: + +/usr/include/x86_64-linux-gnu/bits/stat.h: + +/usr/include/c++/4.7/set: + +/usr/include/c++/4.7/bits/stl_set.h: + +/usr/include/c++/4.7/bits/stl_multiset.h: + +zm_stream.h: + +/usr/include/x86_64-linux-gnu/sys/un.h: + +zm_mpeg.h: + +zm_ffmpeg.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/common.h: + +/usr/include/inttypes.h: + +/usr/include/libavutil/attributes.h: + +/usr/include/libavutil/avconfig.h: + +/usr/include/libavutil/mem.h: + +/usr/include/libavutil/error.h: + +/usr/include/libavutil/avutil.h: + +/usr/include/libavutil/mathematics.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/intfloat_readwrite.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavcodec/avcodec.h: + +/usr/include/libavutil/samplefmt.h: + +/usr/include/libavutil/cpu.h: + +/usr/include/libavutil/dict.h: + +/usr/include/libavutil/log.h: + +/usr/include/libavutil/pixfmt.h: + +/usr/include/libavutil/rational.h: + +/usr/include/libavutil/audioconvert.h: + +/usr/include/libavcodec/version.h: + +/usr/include/libavformat/avformat.h: + +/usr/include/libavformat/avio.h: + +/usr/include/libavutil/common.h: + +/usr/include/libavformat/version.h: + +/usr/include/libswscale/swscale.h: + +zm_camera.h: + +/usr/include/x86_64-linux-gnu/sys/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctls.h: + +/usr/include/x86_64-linux-gnu/asm/ioctls.h: + +/usr/include/asm-generic/ioctls.h: + +/usr/include/linux/ioctl.h: + +/usr/include/x86_64-linux-gnu/asm/ioctl.h: + +/usr/include/asm-generic/ioctl.h: + +/usr/include/x86_64-linux-gnu/bits/ioctl-types.h: + +/usr/include/x86_64-linux-gnu/sys/ttydefaults.h: + +zm_plugin_manager.h: + +/usr/include/x86_64-linux-gnu/sys/dir.h: + +/usr/include/dirent.h: + +/usr/include/x86_64-linux-gnu/bits/dirent.h: + +/usr/include/x86_64-linux-gnu/sys/param.h: + +/usr/include/linux/param.h: + +/usr/include/x86_64-linux-gnu/asm/param.h: + +/usr/include/asm-generic/param.h: + +zm_image_analyser.h: + +/usr/include/c++/4.7/list: + +/usr/include/c++/4.7/bits/stl_list.h: + +/usr/include/c++/4.7/bits/list.tcc: + +/usr/include/c++/4.7/stdexcept: + +/usr/include/c++/4.7/iostream: + +/usr/include/c++/4.7/memory: + +/usr/include/c++/4.7/bits/stl_tempbuf.h: + +/usr/include/c++/4.7/bits/stl_raw_storage_iter.h: + +/usr/include/c++/4.7/backward/auto_ptr.h: + +zm_detector.h: + +/usr/include/syslog.h: + +/usr/include/x86_64-linux-gnu/sys/syslog.h: + +/usr/include/x86_64-linux-gnu/bits/syslog-path.h: + +/usr/include/libgen.h: + +zm_plugin.h: + +/usr/include/dlfcn.h: + +/usr/include/x86_64-linux-gnu/bits/dlfcn.h: + +zm_local_camera.h: + +/usr/include/linux/videodev2.h: + +/usr/include/linux/types.h: + +/usr/include/x86_64-linux-gnu/asm/types.h: + +/usr/include/asm-generic/types.h: + +/usr/include/asm-generic/int-ll64.h: + +/usr/include/x86_64-linux-gnu/asm/bitsperlong.h: + +/usr/include/asm-generic/bitsperlong.h: + +/usr/include/linux/posix_types.h: + +/usr/include/linux/stddef.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types.h: + +/usr/include/x86_64-linux-gnu/asm/posix_types_64.h: diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 000000000..4941a6dd5 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,141 @@ +AUTOMAKE_OPTIONS = gnu + +AM_CPPFLAGS = @MYSQL_CFLAGS@ @FFMPEG_CFLAGS@ -Wall -finline-functions -fomit-frame-pointer +#AM_CXXFLAGS = -frepo + +CLEANFILES = *.rpo + +# This should be set to your CGI directory +cgidir = @CGI_PREFIX@ +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ + +bin_PROGRAMS = \ + zmc \ + zma \ + zmu \ + zms \ + zmf \ + zmstreamer \ + zmfix + +zm_SOURCES = \ + zm_box.cpp \ + zm_buffer.cpp \ + zm_camera.cpp \ + zm_comms.cpp \ + zm_config.cpp \ + zm_coord.cpp \ + zm.cpp \ + zm_db.cpp \ + zm_logger.cpp \ + zm_event.cpp \ + zm_exception.cpp \ + zm_file_camera.cpp \ + zm_ffmpeg_camera.cpp \ + zm_image.cpp \ + zm_jpeg.cpp \ + zm_local_camera.cpp \ + zm_monitor.cpp \ + zm_ffmpeg.cpp \ + zm_mpeg.cpp \ + zm_poly.cpp \ + zm_regexp.cpp \ + zm_remote_camera.cpp \ + zm_remote_camera_http.cpp \ + zm_remote_camera_rtsp.cpp \ + zm_rtp.cpp \ + zm_rtp_ctrl.cpp \ + zm_rtp_data.cpp \ + zm_rtp_source.cpp \ + zm_rtsp.cpp \ + zm_sdp.cpp \ + zm_signal.cpp \ + zm_stream.cpp \ + zm_thread.cpp \ + zm_time.cpp \ + zm_timer.cpp \ + zm_user.cpp \ + zm_utils.cpp \ + zm_zone.cpp \ + zm_detector.cpp \ + zm_plugin.cpp \ + zm_plugin_manager.cpp \ + zm_image_analyser.cpp + +zmc_SOURCES = zmc.cpp $(zm_SOURCES) +zma_SOURCES = zma.cpp $(zm_SOURCES) +zms_SOURCES = zms.cpp $(zm_SOURCES) +zmu_SOURCES = zmu.cpp $(zm_SOURCES) +zmf_SOURCES = zmf.cpp $(zm_SOURCES) +zmstreamer_SOURCES = zmstreamer.cpp $(zm_SOURCES) +zmfix_SOURCES = zmfix.cpp zm_config.cpp zm_regexp.cpp zm_logger.cpp zm_utils.cpp zm_db.cpp zm.cpp + +noinst_HEADERS = \ + jinclude.h \ + zm_box.h \ + zm_buffer.h \ + zm_camera.h \ + zm_comms.h \ + zm_config_defines.h \ + zm_config.h \ + zm_coord.h \ + zm_db.h \ + zm_logger.h \ + zm_event.h \ + zm_exception.h \ + zmf.h \ + zm_file_camera.h \ + zm_ffmpeg_camera.h \ + zm_font.h \ + zm_font.h \ + zm.h \ + zm_image.h \ + zm_jpeg.h \ + zm_local_camera.h \ + zm_mem_utils.h \ + zm_monitor.h \ + zm_ffmpeg.h \ + zm_mpeg.h \ + zm_poly.h \ + zm_regexp.h \ + zm_remote_camera.h \ + zm_remote_camera_http.h \ + zm_remote_camera_rtsp.h \ + zm_rgb.h \ + zm_rtp_ctrl.h \ + zm_rtp_data.h \ + zm_rtp.h \ + zm_rtp_source.h \ + zm_rtsp.h \ + zm_sdp.h \ + zm_signal.h \ + zm_stream.h \ + zm_thread.h \ + zm_time.h \ + zm_timer.h \ + zm_user.h \ + zm_utils.h \ + zm_zone.h \ + zm_detector.h \ + zm_plugin.h \ + zm_plugin_manager.h \ + zm_image_analyser.h + +EXTRA_DIST = \ + zm_config.h.in \ + zm_threaddata.cpp + +dist-hook: + @( rm $(distdir)/zm_config.h ) + +# Yes, you are correct. This is a HACK! +install-exec-hook: + ( cd $(DESTDIR)@bindir@; mkdir -p $(DESTDIR)$(cgidir); mv zms $(DESTDIR)$(cgidir) ) + ( cd $(DESTDIR)$(cgidir); chown $(webuser):$(webgroup) zms; ln -f zms nph-zms ) + ( cd $(DESTDIR)@bindir@; chmod u+s zmfix ) + +uninstall-hook: + ( cd $(DESTDIR)$(cgidir); rm -f zms nph-zms ) + diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 000000000..1d121d968 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,779 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +bin_PROGRAMS = zmc$(EXEEXT) zma$(EXEEXT) zmu$(EXEEXT) zms$(EXEEXT) \ + zmf$(EXEEXT) zmstreamer$(EXEEXT) zmfix$(EXEEXT) +subdir = src +DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/zm_config.h.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = zm_config.h +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" +PROGRAMS = $(bin_PROGRAMS) +am__objects_1 = zm_box.$(OBJEXT) zm_buffer.$(OBJEXT) \ + zm_camera.$(OBJEXT) zm_comms.$(OBJEXT) zm_config.$(OBJEXT) \ + zm_coord.$(OBJEXT) zm.$(OBJEXT) zm_db.$(OBJEXT) \ + zm_logger.$(OBJEXT) zm_event.$(OBJEXT) zm_exception.$(OBJEXT) \ + zm_file_camera.$(OBJEXT) zm_ffmpeg_camera.$(OBJEXT) \ + zm_image.$(OBJEXT) zm_jpeg.$(OBJEXT) zm_local_camera.$(OBJEXT) \ + zm_monitor.$(OBJEXT) zm_ffmpeg.$(OBJEXT) zm_mpeg.$(OBJEXT) \ + zm_poly.$(OBJEXT) zm_regexp.$(OBJEXT) \ + zm_remote_camera.$(OBJEXT) zm_remote_camera_http.$(OBJEXT) \ + zm_remote_camera_rtsp.$(OBJEXT) zm_rtp.$(OBJEXT) \ + zm_rtp_ctrl.$(OBJEXT) zm_rtp_data.$(OBJEXT) \ + zm_rtp_source.$(OBJEXT) zm_rtsp.$(OBJEXT) zm_sdp.$(OBJEXT) \ + zm_signal.$(OBJEXT) zm_stream.$(OBJEXT) zm_thread.$(OBJEXT) \ + zm_time.$(OBJEXT) zm_timer.$(OBJEXT) zm_user.$(OBJEXT) \ + zm_utils.$(OBJEXT) zm_zone.$(OBJEXT) zm_detector.$(OBJEXT) \ + zm_plugin.$(OBJEXT) zm_plugin_manager.$(OBJEXT) \ + zm_image_analyser.$(OBJEXT) +am_zma_OBJECTS = zma.$(OBJEXT) $(am__objects_1) +zma_OBJECTS = $(am_zma_OBJECTS) +zma_LDADD = $(LDADD) +am_zmc_OBJECTS = zmc.$(OBJEXT) $(am__objects_1) +zmc_OBJECTS = $(am_zmc_OBJECTS) +zmc_LDADD = $(LDADD) +am_zmf_OBJECTS = zmf.$(OBJEXT) $(am__objects_1) +zmf_OBJECTS = $(am_zmf_OBJECTS) +zmf_LDADD = $(LDADD) +am_zmfix_OBJECTS = zmfix.$(OBJEXT) zm_config.$(OBJEXT) \ + zm_regexp.$(OBJEXT) zm_logger.$(OBJEXT) zm_utils.$(OBJEXT) \ + zm_db.$(OBJEXT) zm.$(OBJEXT) +zmfix_OBJECTS = $(am_zmfix_OBJECTS) +zmfix_LDADD = $(LDADD) +am_zms_OBJECTS = zms.$(OBJEXT) $(am__objects_1) +zms_OBJECTS = $(am_zms_OBJECTS) +zms_LDADD = $(LDADD) +am_zmstreamer_OBJECTS = zmstreamer.$(OBJEXT) $(am__objects_1) +zmstreamer_OBJECTS = $(am_zmstreamer_OBJECTS) +zmstreamer_LDADD = $(LDADD) +am_zmu_OBJECTS = zmu.$(OBJEXT) $(am__objects_1) +zmu_OBJECTS = $(am_zmu_OBJECTS) +zmu_LDADD = $(LDADD) +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +SOURCES = $(zma_SOURCES) $(zmc_SOURCES) $(zmf_SOURCES) \ + $(zmfix_SOURCES) $(zms_SOURCES) $(zmstreamer_SOURCES) \ + $(zmu_SOURCES) +DIST_SOURCES = $(zma_SOURCES) $(zmc_SOURCES) $(zmf_SOURCES) \ + $(zmfix_SOURCES) $(zms_SOURCES) $(zmstreamer_SOURCES) \ + $(zmu_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(noinst_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +AM_CPPFLAGS = @MYSQL_CFLAGS@ @FFMPEG_CFLAGS@ -Wall -Wno-sign-compare -finline-functions -fomit-frame-pointer +#AM_CXXFLAGS = -frepo +CLEANFILES = *.rpo + +# This should be set to your CGI directory +cgidir = @CGI_PREFIX@ +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ +zm_SOURCES = \ + zm_box.cpp \ + zm_buffer.cpp \ + zm_camera.cpp \ + zm_comms.cpp \ + zm_config.cpp \ + zm_coord.cpp \ + zm.cpp \ + zm_db.cpp \ + zm_logger.cpp \ + zm_event.cpp \ + zm_exception.cpp \ + zm_file_camera.cpp \ + zm_ffmpeg_camera.cpp \ + zm_image.cpp \ + zm_jpeg.cpp \ + zm_local_camera.cpp \ + zm_monitor.cpp \ + zm_ffmpeg.cpp \ + zm_mpeg.cpp \ + zm_poly.cpp \ + zm_regexp.cpp \ + zm_remote_camera.cpp \ + zm_remote_camera_http.cpp \ + zm_remote_camera_rtsp.cpp \ + zm_rtp.cpp \ + zm_rtp_ctrl.cpp \ + zm_rtp_data.cpp \ + zm_rtp_source.cpp \ + zm_rtsp.cpp \ + zm_sdp.cpp \ + zm_signal.cpp \ + zm_stream.cpp \ + zm_thread.cpp \ + zm_time.cpp \ + zm_timer.cpp \ + zm_user.cpp \ + zm_utils.cpp \ + zm_zone.cpp \ + zm_detector.cpp \ + zm_plugin.cpp \ + zm_plugin_manager.cpp \ + zm_image_analyser.cpp + +zmc_SOURCES = zmc.cpp $(zm_SOURCES) +zma_SOURCES = zma.cpp $(zm_SOURCES) +zms_SOURCES = zms.cpp $(zm_SOURCES) +zmu_SOURCES = zmu.cpp $(zm_SOURCES) +zmf_SOURCES = zmf.cpp $(zm_SOURCES) +zmstreamer_SOURCES = zmstreamer.cpp $(zm_SOURCES) +zmfix_SOURCES = zmfix.cpp zm_config.cpp zm_regexp.cpp zm_logger.cpp zm_utils.cpp zm_db.cpp zm.cpp +noinst_HEADERS = \ + jinclude.h \ + zm_box.h \ + zm_buffer.h \ + zm_camera.h \ + zm_comms.h \ + zm_config_defines.h \ + zm_config.h \ + zm_coord.h \ + zm_db.h \ + zm_logger.h \ + zm_event.h \ + zm_exception.h \ + zmf.h \ + zm_file_camera.h \ + zm_ffmpeg_camera.h \ + zm_font.h \ + zm_font.h \ + zm.h \ + zm_image.h \ + zm_jpeg.h \ + zm_local_camera.h \ + zm_mem_utils.h \ + zm_monitor.h \ + zm_ffmpeg.h \ + zm_mpeg.h \ + zm_poly.h \ + zm_regexp.h \ + zm_remote_camera.h \ + zm_remote_camera_http.h \ + zm_remote_camera_rtsp.h \ + zm_rgb.h \ + zm_rtp_ctrl.h \ + zm_rtp_data.h \ + zm_rtp.h \ + zm_rtp_source.h \ + zm_rtsp.h \ + zm_sdp.h \ + zm_signal.h \ + zm_stream.h \ + zm_thread.h \ + zm_time.h \ + zm_timer.h \ + zm_user.h \ + zm_utils.h \ + zm_zone.h \ + zm_detector.h \ + zm_plugin.h \ + zm_plugin_manager.h \ + zm_image_analyser.h + +EXTRA_DIST = \ + zm_config.h.in \ + zm_threaddata.cpp + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +zm_config.h: $(top_builddir)/config.status $(srcdir)/zm_config.h.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) +zma$(EXEEXT): $(zma_OBJECTS) $(zma_DEPENDENCIES) $(EXTRA_zma_DEPENDENCIES) + @rm -f zma$(EXEEXT) + $(CXXLINK) $(zma_OBJECTS) $(zma_LDADD) $(LIBS) +zmc$(EXEEXT): $(zmc_OBJECTS) $(zmc_DEPENDENCIES) $(EXTRA_zmc_DEPENDENCIES) + @rm -f zmc$(EXEEXT) + $(CXXLINK) $(zmc_OBJECTS) $(zmc_LDADD) $(LIBS) +zmf$(EXEEXT): $(zmf_OBJECTS) $(zmf_DEPENDENCIES) $(EXTRA_zmf_DEPENDENCIES) + @rm -f zmf$(EXEEXT) + $(CXXLINK) $(zmf_OBJECTS) $(zmf_LDADD) $(LIBS) +zmfix$(EXEEXT): $(zmfix_OBJECTS) $(zmfix_DEPENDENCIES) $(EXTRA_zmfix_DEPENDENCIES) + @rm -f zmfix$(EXEEXT) + $(CXXLINK) $(zmfix_OBJECTS) $(zmfix_LDADD) $(LIBS) +zms$(EXEEXT): $(zms_OBJECTS) $(zms_DEPENDENCIES) $(EXTRA_zms_DEPENDENCIES) + @rm -f zms$(EXEEXT) + $(CXXLINK) $(zms_OBJECTS) $(zms_LDADD) $(LIBS) +zmstreamer$(EXEEXT): $(zmstreamer_OBJECTS) $(zmstreamer_DEPENDENCIES) $(EXTRA_zmstreamer_DEPENDENCIES) + @rm -f zmstreamer$(EXEEXT) + $(CXXLINK) $(zmstreamer_OBJECTS) $(zmstreamer_LDADD) $(LIBS) +zmu$(EXEEXT): $(zmu_OBJECTS) $(zmu_DEPENDENCIES) $(EXTRA_zmu_DEPENDENCIES) + @rm -f zmu$(EXEEXT) + $(CXXLINK) $(zmu_OBJECTS) $(zmu_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_box.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_buffer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_camera.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_comms.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_coord.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_db.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_detector.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_event.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_exception.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_ffmpeg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_ffmpeg_camera.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_file_camera.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_image.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_image_analyser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_jpeg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_local_camera.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_logger.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_mpeg.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_plugin.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_plugin_manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_poly.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_regexp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_remote_camera.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_remote_camera_http.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_remote_camera_rtsp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_rtp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_rtp_ctrl.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_rtp_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_rtp_source.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_rtsp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_sdp.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_signal.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_stream.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_thread.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_time.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_timer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_user.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_utils.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zm_zone.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zma.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmfix.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zms.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmstreamer.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/zmu.Po@am__quote@ + +.cpp.o: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(bindir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: install-am install-exec-am install-strip uninstall-am + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic ctags dist-hook distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-binPROGRAMS \ + install-data install-data-am install-dvi install-dvi-am \ + install-exec install-exec-am install-exec-hook install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-hook + + +dist-hook: + @( rm $(distdir)/zm_config.h ) + +# Yes, you are correct. This is a HACK! +install-exec-hook: + ( cd $(DESTDIR)@bindir@; mkdir -p $(DESTDIR)$(cgidir); mv zms $(DESTDIR)$(cgidir) ) + ( cd $(DESTDIR)$(cgidir); chown $(webuser):$(webgroup) zms; ln -f zms nph-zms ) + ( cd $(DESTDIR)@bindir@; chmod u+s zmfix ) + +uninstall-hook: + ( cd $(DESTDIR)$(cgidir); rm -f zms nph-zms ) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/jinclude.h b/src/jinclude.h new file mode 100644 index 000000000..e1065bc6f --- /dev/null +++ b/src/jinclude.h @@ -0,0 +1,91 @@ +/* + * jinclude.h + * + * Copyright (C) 2001-2008 Philip Coombes + * This file is part of the Independent JPEG Group's software. + * For conditions of distribution and use, see the accompanying README file. + * + * This file exists to provide a single place to fix any problems with + * including the wrong system include files. (Common problems are taken + * care of by the standard jconfig symbols, but on really weird systems + * you may have to edit this file.) + * + * NOTE: this file is NOT intended to be included by applications using the + * JPEG library. Most applications need only include jpeglib.h. + */ + + +/* Include auto-config file to find out which system include files we need. */ + +#include "jconfig.h" /* auto configuration options */ +#define JCONFIG_INCLUDED /* so that jpeglib.h doesn't do it again */ + +/* + * We need the NULL macro and size_t typedef. + * On an ANSI-conforming system it is sufficient to include . + * Otherwise, we get them from or ; we may have to + * pull in as well. + * Note that the core JPEG library does not require ; + * only the default error handler and data source/destination modules do. + * But we must pull it in because of the references to FILE in jpeglib.h. + * You can remove those references if you want to compile without . + */ + +#ifdef HAVE_STDDEF_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_SYS_TYPES_H +#include +#endif + +#include + +/* + * We need memory copying and zeroing functions, plus strncpy(). + * ANSI and System V implementations declare these in . + * BSD doesn't have the mem() functions, but it does have bcopy()/bzero(). + * Some systems may declare memset and memcpy in . + * + * NOTE: we assume the size parameters to these functions are of type size_t. + * Change the casts in these macros if not! + */ + +#ifdef NEED_BSD_STRINGS + +#include +#define MEMZERO(target,size) bzero((void *)(target), (size_t)(size)) +#define MEMCOPY(dest,src,size) bcopy((const void *)(src), (void *)(dest), (size_t)(size)) + +#else /* not BSD, assume ANSI/SysV string lib */ + +#include +#define MEMZERO(target,size) memset((void *)(target), 0, (size_t)(size)) +#define MEMCOPY(dest,src,size) memcpy((void *)(dest), (const void *)(src), (size_t)(size)) + +#endif + +/* + * In ANSI C, and indeed any rational implementation, size_t is also the + * type returned by sizeof(). However, it seems there are some irrational + * implementations out there, in which sizeof() returns an int even though + * size_t is defined as long or unsigned long. To ensure consistent results + * we always use this SIZEOF() macro in place of using sizeof() directly. + */ + +#define SIZEOF(object) ((size_t) sizeof(object)) + +/* + * The modules that use fread() and fwrite() always invoke them through + * these macros. On some systems you may need to twiddle the argument casts. + * CAUTION: argument order is different from underlying functions! + */ + +#define JFREAD(file,buf,sizeofbuf) \ + ((size_t) fread((void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) +#define JFWRITE(file,buf,sizeofbuf) \ + ((size_t) fwrite((const void *) (buf), (size_t) 1, (size_t) (sizeofbuf), (file))) diff --git a/src/zm.cpp b/src/zm.cpp new file mode 100644 index 000000000..311c2b77b --- /dev/null +++ b/src/zm.cpp @@ -0,0 +1,22 @@ +// +// ZoneMinder Core Implementation, $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. +// + +#include "zm.h" + +// This space intentionally left blank diff --git a/src/zm.h b/src/zm.h new file mode 100644 index 000000000..914a1aae1 --- /dev/null +++ b/src/zm.h @@ -0,0 +1,35 @@ +// +// ZoneMinder Core Interfaces, $Date$, $Revision$ +// $Copyright$ +// +// 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. +// + +#ifndef ZM_H +#define ZM_H + +#include "zm_config.h" +#include "zm_logger.h" + +extern "C" +{ +#if !HAVE_DECL_ROUND +double round(double); +#endif +} + +#include + +#endif // ZM_H diff --git a/src/zm_box.cpp b/src/zm_box.cpp new file mode 100644 index 000000000..2cb8c9a5e --- /dev/null +++ b/src/zm_box.cpp @@ -0,0 +1,23 @@ +// +// ZoneMinder Box Class Implementation, $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. +// + +#include "zm.h" +#include "zm_box.h" + +// This section deliberately left blank diff --git a/src/zm_box.h b/src/zm_box.h new file mode 100644 index 000000000..8a18b8847 --- /dev/null +++ b/src/zm_box.h @@ -0,0 +1,70 @@ +// +// ZoneMinder Box Class Interfaces, $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. +// + +#ifndef ZM_BOX_H +#define ZM_BOX_H + +#include "zm.h" +#include "zm_coord.h" + +#include + +// +// Class used for storing a box, which is defined as a region +// defined by two coordinates +// +class Box +{ +private: + Coord lo, hi; + Coord size; + +public: + inline Box() + { + } + inline Box( int p_size ) : lo( 0, 0 ), hi ( p_size-1, p_size-1 ), size( Coord::Range( hi, lo ) ) { } + inline Box( int p_x_size, int p_y_size ) : lo( 0, 0 ), hi ( p_x_size-1, p_y_size-1 ), size( Coord::Range( hi, lo ) ) { } + inline Box( int lo_x, int lo_y, int hi_x, int hi_y ) : lo( lo_x, lo_y ), hi( hi_x, hi_y ), size( Coord::Range( hi, lo ) ) { } + inline Box( const Coord &p_lo, const Coord &p_hi ) : lo( p_lo ), hi( p_hi ), size( Coord::Range( hi, lo ) ) { } + + inline const Coord &Lo() const { return( lo ); } + inline int LoX() const { return( lo.X() ); } + inline int LoY() const { return( lo.Y() ); } + inline const Coord &Hi() const { return( hi ); } + inline int HiX() const { return( hi.X() ); } + inline int HiY() const { return( hi.Y() ); } + inline const Coord &Size() const { return( size ); } + inline int Width() const { return( size.X() ); } + inline int Height() const { return( size.Y() ); } + inline int Area() const { return( size.X()*size.Y() ); } + + inline const Coord Centre() const + { + int mid_x = int(round(lo.X()+(size.X()/2.0))); + int mid_y = int(round(lo.Y()+(size.Y()/2.0))); + return( Coord( mid_x, mid_y ) ); + } + inline bool Inside( const Coord &coord ) const + { + return( coord.X() >= lo.X() && coord.X() <= hi.X() && coord.Y() >= lo.Y() && coord.Y() <= hi.Y() ); + } +}; + +#endif // ZM_BOX_H diff --git a/src/zm_buffer.cpp b/src/zm_buffer.cpp new file mode 100644 index 000000000..384f45bcc --- /dev/null +++ b/src/zm_buffer.cpp @@ -0,0 +1,69 @@ +/* + * ZoneMinder flexible memory class implementation, $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. +*/ + +#include + +#include "zm.h" +#include "zm_buffer.h" + +unsigned int Buffer::assign( const unsigned char *pStorage, unsigned int pSize ) +{ + if ( mAllocation < pSize ) + { + delete[] mStorage; + mAllocation = pSize; + mHead = mStorage = new unsigned char[pSize]; + } + mSize = pSize; + memcpy( mStorage, pStorage, mSize ); + mHead = mStorage; + mTail = mHead + mSize; + return( mSize ); +} + +unsigned int Buffer::expand( unsigned int count ) +{ + int spare = mAllocation - mSize; + int headSpace = mHead - mStorage; + int tailSpace = spare - headSpace; + int width = mTail - mHead; + if ( spare > (int)count ) + { + if ( tailSpace < (int)count ) + { + memmove( mStorage, mHead, mSize ); + mHead = mStorage; + mTail = mHead + width; + } + } + else + { + mAllocation += count; + unsigned char *newStorage = new unsigned char[mAllocation]; + if ( mStorage ) + { + memcpy( newStorage, mHead, mSize ); + delete[] mStorage; + } + mStorage = newStorage; + mHead = mStorage; + mTail = mHead + width; + } + return( mSize ); +} diff --git a/src/zm_buffer.h b/src/zm_buffer.h new file mode 100644 index 000000000..3f2343b1a --- /dev/null +++ b/src/zm_buffer.h @@ -0,0 +1,214 @@ +/* + * ZoneMinder Flexible Memory Interface, $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 demTails. + * + * 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. +*/ + +#ifndef ZM_BUFFER_H +#define ZM_BUFFER_H + +#include "zm.h" + +#include + +class Buffer +{ +protected: + unsigned char *mStorage; + unsigned int mAllocation; + unsigned int mSize; + unsigned char *mHead; + unsigned char *mTail; + +public: + Buffer() : mStorage( 0 ), mAllocation( 0 ), mSize( 0 ), mHead( 0 ), mTail( 0 ) + { + } + Buffer( unsigned int pSize ) : mAllocation( pSize ), mSize( 0 ) + { + mHead = mStorage = new unsigned char[mAllocation]; + mTail = mHead; + } + Buffer( const unsigned char *pStorage, unsigned int pSize ) : mAllocation( pSize ), mSize( pSize ) + { + mHead = mStorage = new unsigned char[mSize]; + memcpy( mStorage, pStorage, mSize ); + mTail = mHead + mSize; + } + Buffer( const Buffer &buffer ) : mAllocation( buffer.mSize ), mSize( buffer.mSize ) + { + mHead = mStorage = new unsigned char[mSize]; + memcpy( mStorage, buffer.mHead, mSize ); + mTail = mHead + mSize; + } + ~Buffer() + { + delete[] mStorage; + } + unsigned char *head() const { return( mHead ); } + unsigned char *tail() const { return( mTail ); } + unsigned int size() const { return( mSize ); } + bool empty() const { return( mSize == 0 ); } + unsigned int size( unsigned int pSize ) + { + if ( mSize < pSize ) + { + expand( pSize-mSize ); + } + return( mSize ); + } + //unsigned int Allocation() const { return( mAllocation ); } + + void clear() + { + mSize = 0; + mHead = mTail = mStorage; + } + + unsigned int assign( const unsigned char *pStorage, unsigned int pSize ); + unsigned int assign( const Buffer &buffer ) + { + return( assign( buffer.mHead, buffer.mSize ) ); + } + + // Trim from the front of the buffer + unsigned int consume( unsigned int count ) + { + if ( count > mSize ) + { + Warning( "Attempt to consume %d bytes of buffer, size is only %d bytes", count, mSize ); + count = mSize; + } + mHead += count; + mSize -= count; + tidy( 0 ); + return( count ); + } + // Trim from the end of the buffer + unsigned int shrink( unsigned int count ) + { + if ( count > mSize ) + { + Warning( "Attempt to shrink buffer by %d bytes, size is only %d bytes", count, mSize ); + count = mSize; + } + mSize -= count; + if ( mTail > (mHead + mSize) ) + mTail = mHead + mSize; + tidy( 0 ); + return( count ); + } + // Add to the end of the buffer + unsigned int expand( unsigned int count ); + + // Return pointer to the first pSize bytes and advance the head + unsigned char *extract( unsigned int pSize ) + { + if ( pSize > mSize ) + { + Warning( "Attempt to extract %d bytes of buffer, size is only %d bytes", pSize, mSize ); + pSize = mSize; + } + unsigned char *oldHead = mHead; + mHead += pSize; + mSize -= pSize; + tidy( 0 ); + return( oldHead ); + } + // Add bytes to the end of the buffer + unsigned int append( const unsigned char *pStorage, unsigned int pSize ) + { + expand( pSize ); + memcpy( mTail, pStorage, pSize ); + mTail += pSize; + mSize += pSize; + return( mSize ); + } + unsigned int append( const char *pStorage, unsigned int pSize ) + { + return( append( (const unsigned char *)pStorage, pSize ) ); + } + unsigned int append( const Buffer &buffer ) + { + return( append( buffer.mHead, buffer.mSize ) ); + } + void tidy( bool level=0 ) + { + if ( mHead != mStorage ) + { + if ( mSize == 0 ) + mHead = mTail = mStorage; + else if ( level >= 1 ) + { + if ( (mHead-mStorage) > mSize ) + { + memcpy( mStorage, mHead, mSize ); + mHead = mStorage; + mTail = mHead + mSize; + } + else if ( level >= 2 ) + { + memmove( mStorage, mHead, mSize ); + mHead = mStorage; + mTail = mHead + mSize; + } + } + } + } + + Buffer &operator=( const Buffer &buffer ) + { + assign( buffer ); + return( *this ); + } + Buffer &operator+=( const Buffer &buffer ) + { + append( buffer ); + return( *this ); + } + Buffer &operator+=( unsigned int count ) + { + expand( count ); + return( *this ); + } + Buffer &operator-=( unsigned int count ) + { + consume( count ); + return( *this ); + } + operator unsigned char *() const + { + return( mHead ); + } + operator char *() const + { + return( (char *)mHead ); + } + unsigned char *operator+(int offset) const + { + return( (unsigned char *)(mHead+offset) ); + } + unsigned char operator[](int index) const + { + return( *(mHead+index) ); + } + operator int () const + { + return( (int)mSize ); + } +}; + +#endif // ZM_BUFFER_H diff --git a/src/zm_camera.cpp b/src/zm_camera.cpp new file mode 100644 index 000000000..18950d341 --- /dev/null +++ b/src/zm_camera.cpp @@ -0,0 +1,52 @@ +// +// ZoneMinder Camera Class Implementation, $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. +// + +#include "zm.h" +#include "zm_camera.h" + +Camera::Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + id( p_id ), + type( p_type ), + width( p_width), + height( p_height ), + colours( p_colours ), + subpixelorder( p_subpixelorder ), + brightness( p_brightness ), + hue( p_hue ), + colour( p_colour ), + contrast( p_contrast ), + capture( p_capture ) +{ + pixels = width * height; + imagesize = pixels * colours; + + Debug(2,"New camera id: %d width: %d height: %d colours: %d subpixelorder: %d capture: %d",id,width,height,colours,subpixelorder,capture); + + /* Because many loops are unrolled and work on 16 colours/time or 4 pixels/time, we have to meet requirements */ + if((colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB32) && (imagesize % 16) != 0) { + Fatal("Image size is not multiples of 16"); + } else if(colours == ZM_COLOUR_RGB24 && ((imagesize % 16) != 0 || (imagesize % 12) != 0)) { + Fatal("Image size is not multiples of 12 and 16"); + } +} + +Camera::~Camera() +{ +} + diff --git a/src/zm_camera.h b/src/zm_camera.h new file mode 100644 index 000000000..8713d3956 --- /dev/null +++ b/src/zm_camera.h @@ -0,0 +1,81 @@ +// +// ZoneMinder Camera Class Interface, $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. +// + +#ifndef ZM_CAMERA_H +#define ZM_CAMERA_H + +#include +#include + +#include "zm_image.h" + +// +// Abstract base class for cameras. This is intended just to express +// common attributes +// +class Camera +{ +protected: + typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC } SourceType; + + int id; + SourceType type; + unsigned int width; + unsigned int height; + unsigned int colours; + unsigned int subpixelorder; + unsigned int pixels; + unsigned int imagesize; + int brightness; + int hue; + int colour; + int contrast; + bool capture; + +public: + Camera( int p_id, SourceType p_type, int p_width, int p_height, int p_colours, int p_subpixelorder, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + virtual ~Camera(); + + int getId() const { return( id ); } + SourceType Type() const { return( type ); } + bool IsLocal() const { return( type == LOCAL_SRC ); } + bool IsRemote() const { return( type == REMOTE_SRC ); } + bool IsFile() const { return( type == FILE_SRC ); } + bool IsFfmpeg() const { return( type == FFMPEG_SRC ); } + unsigned int Width() const { return( width ); } + unsigned int Height() const { return( height ); } + unsigned int Colours() const { return( colours ); } + unsigned int SubpixelOrder() const { return( subpixelorder ); } + unsigned int Pixels() const { return( pixels ); } + unsigned int ImageSize() const { return( imagesize ); } + + virtual int Brightness( int/*p_brightness*/=-1 ) { return( -1 ); } + virtual int Hue( int/*p_hue*/=-1 ) { return( -1 ); } + virtual int Colour( int/*p_colour*/=-1 ) { return( -1 ); } + virtual int Contrast( int/*p_contrast*/=-1 ) { return( -1 ); } + + bool CanCapture() const { return( capture ); } + + virtual int PrimeCapture() { return( 0 ); } + virtual int PreCapture()=0; + virtual int Capture( Image &image )=0; + virtual int PostCapture()=0; +}; + +#endif // ZM_CAMERA_H diff --git a/src/zm_comms.cpp b/src/zm_comms.cpp new file mode 100644 index 000000000..b30bed1d5 --- /dev/null +++ b/src/zm_comms.cpp @@ -0,0 +1,711 @@ +// +// ZoneMinder Communications Class Implementation, $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. +// + +#include "zm_comms.h" + +#include "zm_logger.h" + +#include +#include +#include +//#include +#include +#include +//#include +#include +#include +//#include +//#include +#include + +int CommsBase::readV( int iovcnt, /* const void *, int, */ ... ) +{ + va_list arg_ptr; + //struct iovec iov[iovcnt]; + struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); + + va_start( arg_ptr, iovcnt ); + for ( int i = 0; i < iovcnt; i++ ) + { + iov[i].iov_base = va_arg( arg_ptr, void * ); + iov[i].iov_len = va_arg( arg_ptr, int ); + } + va_end( arg_ptr ); + + int nBytes = ::readv( mRd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); + return( nBytes ); +} + +int CommsBase::writeV( int iovcnt, /* const void *, int, */ ... ) +{ + va_list arg_ptr; + //struct iovec iov[iovcnt]; + struct iovec *iov = (struct iovec *)alloca( sizeof(struct iovec)*iovcnt ); + + va_start( arg_ptr, iovcnt ); + for ( int i = 0; i < iovcnt; i++ ) + { + iov[i].iov_base = va_arg( arg_ptr, void * ); + iov[i].iov_len = va_arg( arg_ptr, int ); + } + va_end( arg_ptr ); + + ssize_t nBytes = ::writev( mWd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); + return( nBytes ); +} + +bool Pipe::open() +{ + if ( ::pipe( mFd ) < 0 ) + { + Error( "pipe(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + + return( true ); +} + +bool Pipe::close() +{ + if ( mFd[0] > -1 ) ::close( mFd[0] ); + mFd[0] = -1; + if ( mFd[1] > -1 ) ::close( mFd[1] ); + mFd[1] = -1; + return( true ); +} + +bool Pipe::setBlocking( bool blocking ) +{ + int flags; + + /* Now set it for non-blocking I/O */ + if ( (flags = fcntl( mFd[1], F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + if ( blocking ) + { + flags &= ~O_NONBLOCK; + } + else + { + flags |= O_NONBLOCK; + } + if ( fcntl( mFd[1], F_SETFL, flags ) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + + return( true ); +} + +SockAddr::SockAddr( const struct sockaddr *addr ) : mAddr( addr ) +{ +} + +SockAddr *SockAddr::newSockAddr( const struct sockaddr &addr, socklen_t len ) +{ + if ( addr.sa_family == AF_INET && len == SockAddrInet::addrSize() ) + { + return( new SockAddrInet( (const struct sockaddr_in *)&addr ) ); + } + else if ( addr.sa_family == AF_UNIX && len == SockAddrUnix::addrSize() ) + { + return( new SockAddrUnix( (const struct sockaddr_un *)&addr ) ); + } + Error( "Unable to create new SockAddr from addr family %d with size %d", addr.sa_family, len ); + return( 0 ); +} + +SockAddr *SockAddr::newSockAddr( const SockAddr *addr ) +{ + if ( !addr ) + return( 0 ); + + if ( addr->getDomain() == AF_INET ) + { + return( new SockAddrInet( *(SockAddrInet *)addr ) ); + } + else if ( addr->getDomain() == AF_UNIX ) + { + return( new SockAddrUnix( *(SockAddrUnix *)addr ) ); + } + Error( "Unable to create new SockAddr from addr family %d", addr->getDomain() ); + return( 0 ); +} + +SockAddrInet::SockAddrInet() : SockAddr( (struct sockaddr *)&mAddrIn ) +{ +} + +bool SockAddrInet::resolve( const char *host, const char *serv, const char *proto ) +{ + memset( &mAddrIn, 0, sizeof(mAddrIn) ); + + struct hostent *hostent=0; + if ( !(hostent = ::gethostbyname( host ) ) ) + { + Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); + return( false ); + } + + struct servent *servent=0; + if ( !(servent = ::getservbyname( serv, proto ) ) ) + { + Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); + return( false ); + } + + mAddrIn.sin_port = servent->s_port; + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; + + return( true ); +} + +bool SockAddrInet::resolve( const char *host, int port, const char *proto ) +{ + memset( &mAddrIn, 0, sizeof(mAddrIn) ); + + struct hostent *hostent=0; + if ( !(hostent = ::gethostbyname( host ) ) ) + { + Error( "gethostbyname( %s ), h_errno = %d", host, h_errno ); + return( false ); + } + + mAddrIn.sin_port = htons(port); + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = ((struct in_addr *)(hostent->h_addr))->s_addr; + return( true ); +} + +bool SockAddrInet::resolve( const char *serv, const char *proto ) +{ + memset( &mAddrIn, 0, sizeof(mAddrIn) ); + + struct servent *servent=0; + if ( !(servent = ::getservbyname( serv, proto ) ) ) + { + Error( "getservbyname( %s ), errno = %d, error = %s", serv, errno, strerror(errno) ); + return( false ); + } + + mAddrIn.sin_port = servent->s_port; + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = INADDR_ANY; + + return( true ); +} + +bool SockAddrInet::resolve( int port, const char *proto ) +{ + memset( &mAddrIn, 0, sizeof(mAddrIn) ); + + mAddrIn.sin_port = htons(port); + mAddrIn.sin_family = AF_INET; + mAddrIn.sin_addr.s_addr = INADDR_ANY; + + return( true ); +} + +SockAddrUnix::SockAddrUnix() : SockAddr( (struct sockaddr *)&mAddrUn ) +{ +} + +bool SockAddrUnix::resolve( const char *path, const char *proto ) +{ + memset( &mAddrUn, 0, sizeof(mAddrUn) ); + + strncpy( mAddrUn.sun_path, path, sizeof(mAddrUn.sun_path) ); + mAddrUn.sun_family = AF_UNIX; + + return( true ); +} + +bool Socket::socket() +{ + if ( mSd >= 0 ) + return( true ); + + if ( (mSd = ::socket( getDomain(), getType(), 0 ) ) < 0 ) + { + Error( "socket(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + + int val = 1; + + (void)::setsockopt( mSd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val) ); + (void)::setsockopt( mSd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val) ); + + mState = DISCONNECTED; + + return( true ); +} + +bool Socket::connect() +{ + if ( !socket() ) + return( false ); + + if ( ::connect( mSd, mRemoteAddr->getAddr(), getAddrSize() ) == -1 ) + { + Error( "connect(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + + mState = CONNECTED; + + return( true ); +} + +bool Socket::bind() +{ + if ( !socket() ) + return( false ); + + if ( ::bind( mSd, mLocalAddr->getAddr(), getAddrSize() ) == -1 ) + { + Error( "bind(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + return( true ); +} + +bool Socket::listen() +{ + if ( ::listen( mSd, SOMAXCONN ) == -1 ) + { + Error( "listen(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + + mState = LISTENING; + + return( true ); +} + +bool Socket::accept() +{ + struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); + socklen_t rem_addr_size = getAddrSize(); + + int newSd = -1; + if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) + { + Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + + ::close( mSd ); + mSd = newSd; + + mState = CONNECTED; + + return( true ); +} + +bool Socket::accept( int &newSd ) +{ + struct sockaddr *rem_addr = mLocalAddr->getTempAddr(); + socklen_t rem_addr_size = getAddrSize(); + + newSd = -1; + if ( (newSd = ::accept( mSd, rem_addr, &rem_addr_size )) == -1 ) + { + Error( "accept(), errno = %d, error = %s", errno, strerror(errno) ); + close(); + return( false ); + } + + return( true ); +} + +bool Socket::close() +{ + if ( mSd > -1 ) ::close( mSd ); + mSd = -1; + mState = CLOSED; + return( true ); +} + +int Socket::bytesToRead() const +{ + int bytes_to_read = 0; + + if ( ioctl( mSd, FIONREAD, &bytes_to_read ) < 0 ) + { + Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( bytes_to_read ); +} + +bool Socket::getBlocking( bool &blocking ) +{ + int flags; + + if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + blocking = (flags & O_NONBLOCK); + return( true ); +} + +bool Socket::setBlocking( bool blocking ) +{ +#if 0 + // ioctl is apparently not recommended + int ioctl_arg = !blocking; + if ( ioctl( mSd, FIONBIO, &ioctl_arg ) < 0 ) + { + Error( "ioctl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); +#endif + + int flags; + + /* Now set it for non-blocking I/O */ + if ( (flags = fcntl( mSd, F_GETFL )) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + if ( blocking ) + { + flags &= ~O_NONBLOCK; + } + else + { + flags |= O_NONBLOCK; + } + if ( fcntl( mSd, F_SETFL, flags ) < 0 ) + { + Error( "fcntl(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + + return( true ); +} + +bool Socket::getSendBufferSize( int &buffersize ) const +{ + socklen_t optlen = sizeof(buffersize); + if ( getsockopt( mSd, SOL_SOCKET, SO_SNDBUF, &buffersize, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( buffersize ); +} + +bool Socket::getRecvBufferSize( int &buffersize ) const +{ + socklen_t optlen = sizeof(buffersize); + if ( getsockopt( mSd, SOL_SOCKET, SO_RCVBUF, &buffersize, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( -1 ); + } + return( buffersize ); +} + +bool Socket::setSendBufferSize( int buffersize ) +{ + if ( setsockopt( mSd, SOL_SOCKET, SO_SNDBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); +} + +bool Socket::setRecvBufferSize( int buffersize ) +{ + if ( setsockopt( mSd, SOL_SOCKET, SO_RCVBUF, (char *)&buffersize, sizeof(buffersize)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); +} + +bool Socket::getRouting( bool &route ) const +{ + int dontRoute; + socklen_t optlen = sizeof(dontRoute); + if ( getsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, &dontRoute, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + route = !dontRoute; + return( true ); +} + +bool Socket::setRouting( bool route ) +{ + int dontRoute = !route; + if ( setsockopt( mSd, SOL_SOCKET, SO_DONTROUTE, (char *)&dontRoute, sizeof(dontRoute)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); +} + +bool Socket::getNoDelay( bool &nodelay ) const +{ + int int_nodelay; + socklen_t optlen = sizeof(int_nodelay); + if ( getsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, &int_nodelay, &optlen ) < 0 ) + { + Error( "getsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + nodelay = int_nodelay; + return( true ); +} + +bool Socket::setNoDelay( bool nodelay ) +{ + int int_nodelay = nodelay; + + if ( setsockopt( mSd, IPPROTO_TCP, TCP_NODELAY, (char *)&int_nodelay, sizeof(int_nodelay)) < 0 ) + { + Error( "setsockopt(), errno = %d, error = %s", errno, strerror(errno) ); + return( false ); + } + return( true ); +} + +bool TcpInetServer::listen() +{ + return( Socket::listen() ); +} + +bool TcpInetServer::accept() +{ + return( Socket::accept() ); +} + +bool TcpInetServer::accept( TcpInetSocket *&newSocket ) +{ + int newSd = -1; + newSocket = 0; + + if ( !Socket::accept( newSd ) ) + return( false ); + + newSocket = new TcpInetSocket( *this, newSd ); + + return( true ); +} + +bool TcpUnixServer::accept( TcpUnixSocket *&newSocket ) +{ + int newSd = -1; + newSocket = 0; + + if ( !Socket::accept( newSd ) ) + return( false ); + + newSocket = new TcpUnixSocket( *this, newSd ); + + return( true ); +} + +Select::Select() : mHasTimeout( false ), mMaxFd( -1 ) +{ +} + +Select::Select( struct timeval timeout ) : mMaxFd( -1 ) +{ + setTimeout( timeout ); +} + +Select::Select( int timeout ) : mMaxFd( -1 ) +{ + setTimeout( timeout ); +} + +Select::Select( double timeout ) : mMaxFd( -1 ) +{ + setTimeout( timeout ); +} + +void Select::setTimeout( int timeout ) +{ + mTimeout.tv_sec = timeout; + mTimeout.tv_usec = 0; + mHasTimeout = true; +} + +void Select::setTimeout( double timeout ) +{ + mTimeout.tv_sec = int(timeout); + mTimeout.tv_usec = suseconds_t((timeout-mTimeout.tv_sec)*1000000.0); + mHasTimeout = true; +} + +void Select::setTimeout( struct timeval timeout ) +{ + mTimeout = timeout; + mHasTimeout = true; +} + +void Select::clearTimeout() +{ + mHasTimeout = false; +} + +void Select::calcMaxFd() +{ + mMaxFd = -1; + for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) + if ( (*iter)->getMaxDesc() > mMaxFd ) + mMaxFd = (*iter)->getMaxDesc(); + for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) + if ( (*iter)->getMaxDesc() > mMaxFd ) + mMaxFd = (*iter)->getMaxDesc(); +} + +bool Select::addReader( CommsBase *comms ) +{ + if ( !comms->isOpen() ) + { + Error( "Unable to add closed reader" ); + return( false ); + } + std::pair result = mReaders.insert( comms ); + if ( result.second ) + if ( comms->getMaxDesc() > mMaxFd ) + mMaxFd = comms->getMaxDesc(); + return( result.second ); +} + +bool Select::deleteReader( CommsBase *comms ) +{ + if ( !comms->isOpen() ) + { + Error( "Unable to add closed reader" ); + return( false ); + } + if ( mReaders.erase( comms ) ) + { + calcMaxFd(); + return( true ); + } + return( false ); +} + +void Select::clearReaders() +{ + mReaders.clear(); + mMaxFd = -1; +} + +bool Select::addWriter( CommsBase *comms ) +{ + std::pair result = mWriters.insert( comms ); + if ( result.second ) + if ( comms->getMaxDesc() > mMaxFd ) + mMaxFd = comms->getMaxDesc(); + return( result.second ); +} + +bool Select::deleteWriter( CommsBase *comms ) +{ + if ( mWriters.erase( comms ) ) + { + calcMaxFd(); + return( true ); + } + return( false ); +} + +void Select::clearWriters() +{ + mWriters.clear(); + mMaxFd = -1; +} + +int Select::wait() +{ + struct timeval tempTimeout = mTimeout; + struct timeval *selectTimeout = mHasTimeout?&tempTimeout:NULL; + + fd_set rfds; + fd_set wfds; + + mReadable.clear(); + FD_ZERO(&rfds); + for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) + FD_SET((*iter)->getReadDesc(),&rfds); + + mWriteable.clear(); + FD_ZERO(&wfds); + for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) + FD_SET((*iter)->getWriteDesc(),&wfds); + + int nFound = select( mMaxFd+1, &rfds, &wfds, NULL, selectTimeout ); + if( nFound == 0 ) + { + Debug( 1, "Select timed out" ); + } + else if ( nFound < 0) + { + Error( "Select error: %s", strerror(errno) ); + } + else + { + for ( CommsSet::iterator iter = mReaders.begin(); iter != mReaders.end(); iter++ ) + if ( FD_ISSET((*iter)->getReadDesc(),&rfds) ) + mReadable.push_back( *iter ); + for ( CommsSet::iterator iter = mWriters.begin(); iter != mWriters.end(); iter++ ) + if ( FD_ISSET((*iter)->getWriteDesc(),&rfds) ) + mWriteable.push_back( *iter ); + } + return( nFound ); +} + +const Select::CommsList &Select::getReadable() const +{ + return( mReadable ); +} + +const Select::CommsList &Select::getWriteable() const +{ + return( mWriteable ); +} diff --git a/src/zm_comms.h b/src/zm_comms.h new file mode 100644 index 000000000..60d4a3ad4 --- /dev/null +++ b/src/zm_comms.h @@ -0,0 +1,889 @@ +// +// ZoneMinder Communicatoions Class Interface, $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. +// + +#ifndef ZM_COMMS_H +#define ZM_COMMS_H + +#include "zm_exception.h" + +#include +#include +#include +#include + +#include +#include + +class CommsException : public Exception +{ +public: + CommsException( const std::string &message ) : Exception( message ) + { + } +}; + +class CommsBase +{ +protected: + const int &mRd; + const int &mWd; + +protected: + CommsBase( int &rd, int &wd ) : mRd( rd ), mWd( wd ) + { + } + virtual ~CommsBase() + { + } + +public: + virtual bool close()=0; + virtual bool isOpen() const=0; + virtual bool isClosed() const=0; + virtual bool setBlocking( bool blocking )=0; + +public: + int getReadDesc() const + { + return( mRd ); + } + int getWriteDesc() const + { + return( mWd ); + } + int getMaxDesc() const + { + return( mRd>mWd?mRd:mWd ); + } + + virtual int read( void *msg, int len ) + { + ssize_t nBytes = ::read( mRd, msg, len ); + if ( nBytes < 0 ) + Debug( 1, "Read of %d bytes max on rd %d failed: %s", len, mRd, strerror(errno) ); + return( nBytes ); + } + virtual int write( const void *msg, int len ) + { + ssize_t nBytes = ::write( mWd, msg, len ); + if ( nBytes < 0 ) + Debug( 1, "Write of %d bytes on wd %d failed: %s", len, mWd, strerror(errno) ); + return( nBytes ); + } + virtual int readV( const struct iovec *iov, int iovcnt ) + { + int nBytes = ::readv( mRd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Readv of %d buffers max on rd %d failed: %s", iovcnt, mRd, strerror(errno) ); + return( nBytes ); + } + virtual int writeV( const struct iovec *iov, int iovcnt ) + { + ssize_t nBytes = ::writev( mWd, iov, iovcnt ); + if ( nBytes < 0 ) + Debug( 1, "Writev of %d buffers on wd %d failed: %s", iovcnt, mWd, strerror(errno) ); + return( nBytes ); + } + virtual int readV( int iovcnt, /* const void *msg1, int len1, */ ... ); + virtual int writeV( int iovcnt, /* const void *msg1, int len1, */ ... ); +}; + +class Pipe : public CommsBase +{ +protected: + int mFd[2]; + +public: + Pipe() : CommsBase( mFd[0], mFd[1] ) + { + mFd[0] = -1; + mFd[1] = -1; + } + ~Pipe() + { + close(); + } + +public: + bool open(); + bool close(); + + bool isOpen() const + { + return( mFd[0] != -1 && mFd[1] != -1 ); + } + int getReadDesc() const + { + return( mFd[0] ); + } + int getWriteDesc() const + { + return( mFd[1] ); + } + + bool setBlocking( bool blocking ); +}; + +class SockAddr +{ +private: + const struct sockaddr *mAddr; + +public: + SockAddr( const struct sockaddr *addr ); + virtual ~SockAddr() + { + } + + static SockAddr *newSockAddr( const struct sockaddr &addr, socklen_t len ); + static SockAddr *newSockAddr( const SockAddr *addr ); + + int getDomain() const + { + return( mAddr?mAddr->sa_family:AF_UNSPEC ); + } + + const struct sockaddr *getAddr() const + { + return( mAddr ); + } + virtual socklen_t getAddrSize() const=0; + virtual struct sockaddr *getTempAddr() const=0; +}; + +class SockAddrInet : public SockAddr +{ +private: + struct sockaddr_in mAddrIn; + struct sockaddr_in mTempAddrIn; + +public: + SockAddrInet(); + SockAddrInet( const SockAddrInet &addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( addr.mAddrIn ) + { + } + SockAddrInet( const struct sockaddr_in *addr ) : SockAddr( (const struct sockaddr *)&mAddrIn ), mAddrIn( *addr ) + { + } + + + bool resolve( const char *host, const char *serv, const char *proto ); + bool resolve( const char *host, int port, const char *proto ); + bool resolve( const char *serv, const char *proto ); + bool resolve( int port, const char *proto ); + + socklen_t getAddrSize() const + { + return( sizeof(mAddrIn) ); + } + struct sockaddr *getTempAddr() const + { + return( (sockaddr *)&mTempAddrIn ); + } + +public: + static socklen_t addrSize() + { + return( sizeof(sockaddr_in) ); + } +}; + +class SockAddrUnix : public SockAddr +{ +private: + struct sockaddr_un mAddrUn; + struct sockaddr_un mTempAddrUn; + +public: + SockAddrUnix(); + SockAddrUnix( const SockAddrUnix &addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( addr.mAddrUn ) + { + } + SockAddrUnix( const struct sockaddr_un *addr ) : SockAddr( (const struct sockaddr *)&mAddrUn ), mAddrUn( *addr ) + { + } + + bool resolve( const char *path, const char *proto ); + + socklen_t getAddrSize() const + { + return( sizeof(mAddrUn) ); + } + struct sockaddr *getTempAddr() const + { + return( (sockaddr *)&mTempAddrUn ); + } + +public: + static socklen_t addrSize() + { + return( sizeof(sockaddr_un) ); + } +}; + +class Socket : public CommsBase +{ +protected: + typedef enum { CLOSED, DISCONNECTED, LISTENING, CONNECTED } State; + +protected: + int mSd; + State mState; + SockAddr *mLocalAddr; + SockAddr *mRemoteAddr; + +protected: + Socket() : CommsBase( mSd, mSd ), mSd( -1 ), mState( CLOSED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) + { + } + Socket( const Socket &socket, int newSd ) : CommsBase( mSd, mSd ), mSd( newSd ), mState( CONNECTED ), mLocalAddr( 0 ), mRemoteAddr( 0 ) + { + if ( socket.mLocalAddr ) + mLocalAddr = SockAddr::newSockAddr( mLocalAddr ); + if ( socket.mRemoteAddr ) + mRemoteAddr = SockAddr::newSockAddr( mRemoteAddr ); + } + virtual ~Socket() + { + close(); + delete mLocalAddr; + delete mRemoteAddr; + } + +public: + bool isOpen() const + { + return( !isClosed() ); + } + bool isClosed() const + { + return( mState == CLOSED ); + } + bool isDisconnected() const + { + return( mState == DISCONNECTED ); + } + bool isConnected() const + { + return( mState == CONNECTED ); + } + virtual bool close(); + +protected: + bool isListening() const + { + return( mState == LISTENING ); + } + +protected: + virtual bool socket(); + virtual bool bind(); + +protected: + virtual bool connect(); + virtual bool listen(); + virtual bool accept(); + virtual bool accept( int & ); + +public: + virtual int send( const void *msg, int len ) const + { + ssize_t nBytes = ::send( mSd, msg, len, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Send of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recv( void *msg, int len ) const + { + ssize_t nBytes = ::recv( mSd, msg, len, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Recv of %d bytes max on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int send( const std::string &msg ) const + { + ssize_t nBytes = ::send( mSd, msg.data(), msg.size(), 0 ); + if ( nBytes < 0 ) + Debug( 1, "Send of string '%s' (%zd bytes) on sd %d failed: %s", msg.c_str(), msg.size(), mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recv( std::string &msg ) const + { + char buffer[msg.capacity()]; + int nBytes = 0; + if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) + { + Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", sizeof(buffer), mSd, strerror(errno) ); + return( nBytes ); + } + buffer[nBytes] = '\0'; + msg = buffer; + return( nBytes ); + } + virtual int recv( std::string &msg, size_t maxLen ) const + { + char buffer[maxLen]; + int nBytes = 0; + if ( (nBytes = ::recv( mSd, buffer, sizeof(buffer), 0 )) < 0 ) + { + Debug( 1, "Recv of %zd bytes max to string on sd %d failed: %s", maxLen, mSd, strerror(errno) ); + return( nBytes ); + } + buffer[nBytes] = '\0'; + msg = buffer; + return( nBytes ); + } + virtual int bytesToRead() const; + + int getDesc() const + { + return( mSd ); + } + //virtual bool isOpen() const + //{ + //return( mSd != -1 ); + //} + + virtual int getDomain() const=0; + virtual int getType() const=0; + virtual const char *getProtocol() const=0; + + const SockAddr *getLocalAddr() const + { + return( mLocalAddr ); + } + const SockAddr *getRemoteAddr() const + { + return( mRemoteAddr ); + } + virtual socklen_t getAddrSize() const=0; + + bool getBlocking( bool &blocking ); + bool setBlocking( bool blocking ); + + bool getSendBufferSize( int & ) const; + bool getRecvBufferSize( int & ) const; + + bool setSendBufferSize( int ); + bool setRecvBufferSize( int ); + + bool getRouting( bool & ) const; + bool setRouting( bool ); + + bool getNoDelay( bool & ) const; + bool setNoDelay( bool ); +}; + +class InetSocket : virtual public Socket +{ +public: + int getDomain() const + { + return( AF_INET ); + } + virtual socklen_t getAddrSize() const + { + return( SockAddrInet::addrSize() ); + } + +protected: + bool resolveLocal( const char *host, const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( host, serv, proto ) ); + } + bool resolveLocal( const char *host, int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( host, port, proto ) ); + } + bool resolveLocal( const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( serv, proto ) ); + } + bool resolveLocal( int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mLocalAddr = addr; + return( addr->resolve( port, proto ) ); + } + + bool resolveRemote( const char *host, const char *serv, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mRemoteAddr = addr; + return( addr->resolve( host, serv, proto ) ); + } + bool resolveRemote( const char *host, int port, const char *proto ) + { + SockAddrInet *addr = new SockAddrInet; + mRemoteAddr = addr; + return( addr->resolve( host, port, proto ) ); + } + +protected: + bool bind( const SockAddrInet &addr ) + { + mLocalAddr = new SockAddrInet( addr ); + return( Socket::bind() ); + } + bool bind( const char *host, const char *serv ) + { + if ( !resolveLocal( host, serv, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( const char *host, int port ) + { + if ( !resolveLocal( host, port, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( const char *serv ) + { + if ( !resolveLocal( serv, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + bool bind( int port ) + { + if ( !resolveLocal( port, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + + bool connect( const SockAddrInet &addr ) + { + mRemoteAddr = new SockAddrInet( addr ); + return( Socket::connect() ); + } + bool connect( const char *host, const char *serv ) + { + if ( !resolveRemote( host, serv, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } + bool connect( const char *host, int port ) + { + if ( !resolveRemote( host, port, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } +}; + +class UnixSocket : virtual public Socket +{ +public: + int getDomain() const + { + return( AF_UNIX ); + } + virtual socklen_t getAddrSize() const + { + return( SockAddrUnix::addrSize() ); + } + +protected: + bool resolveLocal( const char *serv, const char *proto ) + { + SockAddrUnix *addr = new SockAddrUnix; + mLocalAddr = addr; + return( addr->resolve( serv, proto ) ); + } + + bool resolveRemote( const char *path, const char *proto ) + { + SockAddrUnix *addr = new SockAddrUnix; + mRemoteAddr = addr; + return( addr->resolve( path, proto ) ); + } + +protected: + bool bind( const char *path ) + { + if ( !UnixSocket::resolveLocal( path, getProtocol() ) ) + return( false ); + return( Socket::bind() ); + } + + bool connect( const char *path ) + { + if ( !UnixSocket::resolveRemote( path, getProtocol() ) ) + return( false ); + return( Socket::connect() ); + } +}; + +class UdpSocket : virtual public Socket +{ +public: + int getType() const + { + return( SOCK_DGRAM ); + } + const char *getProtocol() const + { + return( "udp" ); + } + +public: + virtual int sendto( const void *msg, int len, const SockAddr *addr=0 ) const + { + ssize_t nBytes = ::sendto( mSd, msg, len, 0, addr?addr->getAddr():NULL, addr?addr->getAddrSize():0 ); + if ( nBytes < 0 ) + Debug( 1, "Sendto of %d bytes on sd %d failed: %s", len, mSd, strerror(errno) ); + return( nBytes ); + } + virtual int recvfrom( void *msg, int len, SockAddr *addr=0 ) const + { + ssize_t nBytes = 0; + if ( addr ) + { + struct sockaddr sockAddr; + socklen_t sockLen; + nBytes = ::recvfrom( mSd, msg, len, 0, &sockAddr, &sockLen ); + if ( nBytes < 0 ) + { + Debug( 1, "Recvfrom of %d bytes max on sd %d (with address) failed: %s", len, mSd, strerror(errno) ); + } + else if ( sockLen ) + { + addr = SockAddr::newSockAddr( sockAddr, sockLen ); + } + } + else + { + nBytes = ::recvfrom( mSd, msg, len, 0, NULL, 0 ); + if ( nBytes < 0 ) + Debug( 1, "Recvfrom of %d bytes max on sd %d (no address) failed: %s", len, mSd, strerror(errno) ); + } + return( nBytes ); + } +}; + +class UdpInetSocket : virtual public UdpSocket, virtual public InetSocket +{ +public: + bool bind( const SockAddrInet &addr ) + { + return( InetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( InetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( InetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( InetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( InetSocket::bind( port ) ); + } + + bool connect( const SockAddrInet &addr ) + { + return( InetSocket::connect( addr ) ); + } + bool connect( const char *host, const char *serv ) + { + return( InetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( InetSocket::connect( host, port ) ); + } +}; + +class UdpUnixSocket : virtual public UdpSocket, virtual public UnixSocket +{ +public: + bool bind( const char *path ) + { + return( UnixSocket::bind( path ) ); + } + + bool connect( const char *path ) + { + return( UnixSocket::connect( path ) ); + } +}; + +class UdpInetClient : public UdpInetSocket +{ +protected: + bool bind( const SockAddrInet &addr ) + { + return( UdpInetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( UdpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( UdpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( UdpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( UdpInetSocket::bind( port ) ); + } + +public: + bool connect( const SockAddrInet &addr ) + { + return( UdpInetSocket::connect( addr ) ); + } + bool connect( const char *host, const char *serv ) + { + return( UdpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( UdpInetSocket::connect( host, port ) ); + } +}; + +class UdpUnixClient : public UdpUnixSocket +{ +public: + bool bind( const char *path ) + { + return( UdpUnixSocket::bind( path ) ); + } + +public: + bool connect( const char *path ) + { + return( UdpUnixSocket::connect( path) ); + } +}; + +class UdpInetServer : public UdpInetSocket +{ +public: + bool bind( const SockAddrInet &addr ) + { + return( UdpInetSocket::bind( addr ) ); + } + bool bind( const char *host, const char *serv ) + { + return( UdpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( UdpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( UdpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( UdpInetSocket::bind( port ) ); + } + +protected: + bool connect( const char *host, const char *serv ) + { + return( UdpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( UdpInetSocket::connect( host, port ) ); + } +}; + +class UdpUnixServer : public UdpUnixSocket +{ +public: + bool bind( const char *path ) + { + return( UdpUnixSocket::bind( path ) ); + } + +protected: + bool connect( const char *path ) + { + return( UdpUnixSocket::connect( path ) ); + } +}; + +class TcpSocket : virtual public Socket +{ +public: + TcpSocket() + { + } + TcpSocket( const TcpSocket &socket, int newSd ) : Socket( socket, newSd ) + { + } + +public: + int getType() const + { + return( SOCK_STREAM ); + } + const char *getProtocol() const + { + return( "tcp" ); + } +}; + +class TcpInetSocket : virtual public TcpSocket, virtual public InetSocket +{ +public: + TcpInetSocket() + { + } + TcpInetSocket( const TcpInetSocket &socket, int newSd ) : TcpSocket( socket, newSd ) + { + } +}; + +class TcpUnixSocket : virtual public TcpSocket, virtual public UnixSocket +{ +public: + TcpUnixSocket() + { + } + TcpUnixSocket( const TcpUnixSocket &socket, int newSd ) : TcpSocket( socket, newSd ) + { + } +}; + +class TcpInetClient : public TcpInetSocket +{ +public: + bool connect( const char *host, const char *serv ) + { + return( TcpInetSocket::connect( host, serv ) ); + } + bool connect( const char *host, int port ) + { + return( TcpInetSocket::connect( host, port ) ); + } +}; + +class TcpUnixClient : public TcpUnixSocket +{ +public: + bool connect( const char *path ) + { + return( TcpUnixSocket::connect( path) ); + } +}; + +class TcpInetServer : public TcpInetSocket +{ +public: + bool bind( const char *host, const char *serv ) + { + return( TcpInetSocket::bind( host, serv ) ); + } + bool bind( const char *host, int port ) + { + return( TcpInetSocket::bind( host, port ) ); + } + bool bind( const char *serv ) + { + return( TcpInetSocket::bind( serv ) ); + } + bool bind( int port ) + { + return( TcpInetSocket::bind( port ) ); + } + +public: + bool isListening() const { return( Socket::isListening() ); } + bool listen(); + bool accept(); + bool accept( TcpInetSocket *&newSocket ); +}; + +class TcpUnixServer : public TcpUnixSocket +{ +public: + bool bind( const char *path ) + { + return( TcpUnixSocket::bind( path ) ); + } + +public: + bool isListening() const { return( Socket::isListening() ); } + bool listen(); + bool accept(); + bool accept( TcpUnixSocket *&newSocket ); +}; + +class Select +{ +public: + typedef std::set CommsSet; + typedef std::vector CommsList; + +protected: + CommsSet mReaders; + CommsSet mWriters; + CommsList mReadable; + CommsList mWriteable; + bool mHasTimeout; + struct timeval mTimeout; + int mMaxFd; + +public: + Select(); + Select( struct timeval timeout ); + Select( int timeout ); + Select( double timeout ); + + void setTimeout( int timeout ); + void setTimeout( double timeout ); + void setTimeout( struct timeval timeout ); + void clearTimeout(); + + void calcMaxFd(); + + bool addReader( CommsBase *comms ); + bool deleteReader( CommsBase *comms ); + void clearReaders(); + + bool addWriter( CommsBase *comms ); + bool deleteWriter( CommsBase *comms ); + void clearWriters(); + + int wait(); + + const CommsList &getReadable() const; + const CommsList &getWriteable() const; +}; + +#endif // ZM_COMMS_H diff --git a/src/zm_config.cpp b/src/zm_config.cpp new file mode 100644 index 000000000..2b54cfeb1 --- /dev/null +++ b/src/zm_config.cpp @@ -0,0 +1,301 @@ +// +// ZoneMinder Configuration Implementation, $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. +// + +#include "zm.h" +#include "zm_db.h" + +#include +#include +#include +#include + +void zmLoadConfig() +{ + FILE *cfg; + char line[512]; + char *val; + if ( (cfg = fopen( ZM_CONFIG, "r")) == NULL ) + { + Fatal( "Can't open %s: %s", ZM_CONFIG, strerror(errno) ); + } + while ( fgets( line, sizeof(line), cfg ) != NULL ) + { + char *line_ptr = line; + + // Trim off any cr/lf line endings + int chomp_len = strcspn( line_ptr, "\r\n" ); + line_ptr[chomp_len] = '\0'; + + // Remove leading white space + int white_len = strspn( line_ptr, " \t" ); + line_ptr += white_len; + + // Check for comment or empty line + if ( *line_ptr == '\0' || *line_ptr == '#' ) + continue; + + // Remove trailing white space + char *temp_ptr = line_ptr+strlen(line_ptr)-1; + while ( *temp_ptr == ' ' || *temp_ptr == '\t' ) + { + *temp_ptr-- = '\0'; + temp_ptr--; + } + + // Now look for the '=' in the middle of the line + temp_ptr = strchr( line_ptr, '=' ); + if ( !temp_ptr ) + { + Warning( "Invalid data in %s: '%s'", ZM_CONFIG, line ); + continue; + } + + // Assign the name and value parts + char *name_ptr = line_ptr; + char *val_ptr = temp_ptr+1; + + // Trim trailing space from the name part + do + { + *temp_ptr = '\0'; + temp_ptr--; + } + while ( *temp_ptr == ' ' || *temp_ptr == '\t' ); + + // Remove leading white space from the value part + white_len = strspn( val_ptr, " \t" ); + val_ptr += white_len; + + val = (char *)malloc( strlen(val_ptr)+1 ); + strncpy( val, val_ptr, strlen(val_ptr)+1 ); + + if ( strcasecmp( name_ptr, "ZM_DB_HOST" ) == 0 ) + staticConfig.DB_HOST = val; + else if ( strcasecmp( name_ptr, "ZM_DB_NAME" ) == 0 ) + staticConfig.DB_NAME = val; + else if ( strcasecmp( name_ptr, "ZM_DB_USER" ) == 0 ) + staticConfig.DB_USER = val; + else if ( strcasecmp( name_ptr, "ZM_DB_PASS" ) == 0 ) + staticConfig.DB_PASS = val; + else if ( strcasecmp( name_ptr, "ZM_PATH_WEB" ) == 0 ) + staticConfig.PATH_WEB = val; + else + { + // We ignore this now as there may be more parameters than the + // c/c++ binaries are bothered about + // Warning( "Invalid parameter '%s' in %s", name_ptr, ZM_CONFIG ); + } + } + fclose( cfg); + zmDbConnect(); + config.Load(); + config.Assign(); +} + +StaticConfig staticConfig; + +ConfigItem::ConfigItem( const char *p_name, const char *p_value, const char *const p_type ) +{ + name = new char[strlen(p_name)+1]; + strcpy( name, p_name ); + value = new char[strlen(p_value)+1]; + strcpy( value, p_value ); + type = new char[strlen(p_type)+1]; + strcpy( type, p_type ); + + //Info( "Created new config item %s = %s (%s)\n", name, value, type ); + + accessed = false; +} + +ConfigItem::~ConfigItem() +{ + delete[] name; + delete[] value; + delete[] type; +} + +void ConfigItem::ConvertValue() const +{ + if ( !strcmp( type, "boolean" ) ) + { + cfg_type = CFG_BOOLEAN; + cfg_value.boolean_value = (bool)strtol( value, 0, 0 ); + } + else if ( !strcmp( type, "integer" ) ) + { + cfg_type = CFG_INTEGER; + cfg_value.integer_value = strtol( value, 0, 10 ); + } + else if ( !strcmp( type, "hexadecimal" ) ) + { + cfg_type = CFG_INTEGER; + cfg_value.integer_value = strtol( value, 0, 16 ); + } + else if ( !strcmp( type, "decimal" ) ) + { + cfg_type = CFG_DECIMAL; + cfg_value.decimal_value = strtod( value, 0 ); + } + else + { + cfg_type = CFG_STRING; + cfg_value.string_value = value; + } + accessed = true; +} + +bool ConfigItem::BooleanValue() const +{ + if ( !accessed ) + ConvertValue(); + + if ( cfg_type != CFG_BOOLEAN ) + { + Error( "Attempt to fetch boolean value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } + + return( cfg_value.boolean_value ); +} + +int ConfigItem::IntegerValue() const +{ + if ( !accessed ) + ConvertValue(); + + if ( cfg_type != CFG_INTEGER ) + { + Error( "Attempt to fetch integer value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } + + return( cfg_value.integer_value ); +} + +double ConfigItem::DecimalValue() const +{ + if ( !accessed ) + ConvertValue(); + + if ( cfg_type != CFG_DECIMAL ) + { + Error( "Attempt to fetch decimal value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } + + return( cfg_value.decimal_value ); +} + +const char *ConfigItem::StringValue() const +{ + if ( !accessed ) + ConvertValue(); + + if ( cfg_type != CFG_STRING ) + { + Error( "Attempt to fetch string value for %s, actual type is %s. Try running 'zmupdate.pl -f' to reload config.", name, type ); + exit( -1 ); + } + + return( cfg_value.string_value ); +} + +Config::Config() +{ + n_items = 0; + items = 0; +} + +Config::~Config() +{ + if ( items ) + { + for ( int i = 0; i < n_items; i++ ) + { + delete items[i]; + } + delete[] items; + } +} + +void Config::Load() +{ + static char sql[ZM_SQL_SML_BUFSIZ]; + + strncpy( sql, "select Name, Value, Type from Config order by Id", sizeof(sql) ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + n_items = mysql_num_rows( result ); + + if ( n_items <= ZM_MAX_CFG_ID ) + { + Error( "Config mismatch, expected %d items, read %d. Try running 'zmupdate.pl -f' to reload config.", ZM_MAX_CFG_ID+1, n_items ); + exit( -1 ); + } + + items = new ConfigItem *[n_items]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + items[i] = new ConfigItem( dbrow[0], dbrow[1], dbrow[2] ); + } + mysql_free_result( result ); +} + +void Config::Assign() +{ +ZM_CFG_ASSIGN_LIST +} + +const ConfigItem &Config::Item( int id ) +{ + if ( !n_items ) + { + Load(); + Assign(); + } + + if ( id < 0 || id > ZM_MAX_CFG_ID ) + { + Error( "Attempt to access invalid config, id = %d. Try running 'zmupdate.pl -f' to reload config.", id ); + exit( -1 ); + } + + ConfigItem *item = items[id]; + + if ( !item ) + { + Error( "Can't find config item %d", id ); + exit( -1 ); + } + + return( *item ); +} + +Config config; diff --git a/src/zm_config.h b/src/zm_config.h new file mode 100644 index 000000000..10928a82e --- /dev/null +++ b/src/zm_config.h @@ -0,0 +1,135 @@ +// +// ZoneMinder Configuration, $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. +// + +#ifndef ZM_CONFIG_H +#define ZM_CONFIG_H + +#include "config.h" +#include "zm_config_defines.h" + +#include + +#define ZM_CONFIG "/etc/zm/zm.conf" // Path to config file +#define ZM_VERSION "1.25.0" // ZoneMinder Version + +#define ZM_HAS_V4L1 0 +#define ZM_HAS_V4L2 1 +#define ZM_HAS_V4L 1 + +#ifdef HAVE_LIBAVFORMAT +#define ZM_HAS_FFMPEG 1 +#endif // HAVE_LIBAVFORMAT + +#define ZM_MAX_IMAGE_WIDTH 2048 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_HEIGHT 1536 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_COLOURS 4 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT) +#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS) + +#define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP +#define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP + +#define ZM_SQL_SML_BUFSIZ 256 // Size of SQL buffer +#define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer +#define ZM_SQL_LGE_BUFSIZ 8192 // Size of SQL buffer + +#define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer + +#define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle +#define ZM_SAMPLE_RATE int(1000000/ZM_MAX_FPS) // A general nyquist sample frequency for delays etc +#define ZM_SUSPENDED_RATE int(1000000/4) // A slower rate for when disabled etc + +extern void zmLoadConfig(); + +struct StaticConfig +{ + std::string DB_HOST; + std::string DB_NAME; + std::string DB_USER; + std::string DB_PASS; + std::string PATH_WEB; +}; + +extern StaticConfig staticConfig; + +class ConfigItem +{ +private: + char *name; + char *value; + char *type; + + mutable enum { CFG_BOOLEAN, CFG_INTEGER, CFG_DECIMAL, CFG_STRING } cfg_type; + mutable union + { + bool boolean_value; + int integer_value; + double decimal_value; + char *string_value; + } cfg_value; + mutable bool accessed; + +public: + ConfigItem( const char *p_name, const char *p_value, const char *const p_type ); + ~ConfigItem(); + void ConvertValue() const; + bool BooleanValue() const; + int IntegerValue() const; + double DecimalValue() const; + const char *StringValue() const; + + inline operator bool() const + { + return( BooleanValue() ); + } + inline operator int() const + { + return( IntegerValue() ); + } + inline operator double() const + { + return( DecimalValue() ); + } + inline operator const char *() const + { + return( StringValue() ); + } +}; + +class Config +{ +public: + ZM_CFG_DECLARE_LIST + +private: + int n_items; + ConfigItem **items; + +public: + Config(); + ~Config(); + + void Load(); + void Assign(); + const ConfigItem &Item( int id ); +}; + +extern Config config; + +#endif // ZM_CONFIG_H diff --git a/src/zm_config.h.in b/src/zm_config.h.in new file mode 100644 index 000000000..01098c90f --- /dev/null +++ b/src/zm_config.h.in @@ -0,0 +1,135 @@ +// +// ZoneMinder Configuration, $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. +// + +#ifndef ZM_CONFIG_H +#define ZM_CONFIG_H + +#include "config.h" +#include "zm_config_defines.h" + +#include + +#define ZM_CONFIG "@ZM_CONFIG@" // Path to config file +#define ZM_VERSION "@VERSION@" // ZoneMinder Version + +#define ZM_HAS_V4L1 @ZM_HAS_V4L1@ +#define ZM_HAS_V4L2 @ZM_HAS_V4L2@ +#define ZM_HAS_V4L @ZM_HAS_V4L@ + +#ifdef HAVE_LIBAVFORMAT +#define ZM_HAS_FFMPEG 1 +#endif // HAVE_LIBAVFORMAT + +#define ZM_MAX_IMAGE_WIDTH 2048 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_HEIGHT 1536 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_COLOURS 4 // The largest image we imagine ever handling +#define ZM_MAX_IMAGE_DIM (ZM_MAX_IMAGE_WIDTH*ZM_MAX_IMAGE_HEIGHT) +#define ZM_MAX_IMAGE_SIZE (ZM_MAX_IMAGE_DIM*ZM_MAX_IMAGE_COLOURS) + +#define ZM_SCALE_BASE 100 // The factor by which we bump up 'scale' to simulate FP +#define ZM_RATE_BASE 100 // The factor by which we bump up 'rate' to simulate FP + +#define ZM_SQL_SML_BUFSIZ 256 // Size of SQL buffer +#define ZM_SQL_MED_BUFSIZ 1024 // Size of SQL buffer +#define ZM_SQL_LGE_BUFSIZ 8192 // Size of SQL buffer + +#define ZM_NETWORK_BUFSIZ 32768 // Size of network buffer + +#define ZM_MAX_FPS 30 // The maximum frame rate we expect to handle +#define ZM_SAMPLE_RATE int(1000000/ZM_MAX_FPS) // A general nyquist sample frequency for delays etc +#define ZM_SUSPENDED_RATE int(1000000/4) // A slower rate for when disabled etc + +extern void zmLoadConfig(); + +struct StaticConfig +{ + std::string DB_HOST; + std::string DB_NAME; + std::string DB_USER; + std::string DB_PASS; + std::string PATH_WEB; +}; + +extern StaticConfig staticConfig; + +class ConfigItem +{ +private: + char *name; + char *value; + char *type; + + mutable enum { CFG_BOOLEAN, CFG_INTEGER, CFG_DECIMAL, CFG_STRING } cfg_type; + mutable union + { + bool boolean_value; + int integer_value; + double decimal_value; + char *string_value; + } cfg_value; + mutable bool accessed; + +public: + ConfigItem( const char *p_name, const char *p_value, const char *const p_type ); + ~ConfigItem(); + void ConvertValue() const; + bool BooleanValue() const; + int IntegerValue() const; + double DecimalValue() const; + const char *StringValue() const; + + inline operator bool() const + { + return( BooleanValue() ); + } + inline operator int() const + { + return( IntegerValue() ); + } + inline operator double() const + { + return( DecimalValue() ); + } + inline operator const char *() const + { + return( StringValue() ); + } +}; + +class Config +{ +public: + ZM_CFG_DECLARE_LIST + +private: + int n_items; + ConfigItem **items; + +public: + Config(); + ~Config(); + + void Load(); + void Assign(); + const ConfigItem &Item( int id ); +}; + +extern Config config; + +#endif // ZM_CONFIG_H diff --git a/src/zm_config_defines.h b/src/zm_config_defines.h new file mode 100644 index 000000000..e16183ea9 --- /dev/null +++ b/src/zm_config_defines.h @@ -0,0 +1,676 @@ +// The file is autogenerated by zmconfgen.pl +// Do not edit this file as any changes will be overwritten + +#define ZM_LANG_DEFAULT 0 +#define ZM_OPT_USE_AUTH 1 +#define ZM_AUTH_TYPE 2 +#define ZM_AUTH_RELAY 3 +#define ZM_AUTH_HASH_SECRET 4 +#define ZM_AUTH_HASH_IPS 5 +#define ZM_AUTH_HASH_LOGINS 6 +#define ZM_DIR_EVENTS 7 +#define ZM_USE_DEEP_STORAGE 8 +#define ZM_DIR_IMAGES 9 +#define ZM_DIR_SOUNDS 10 +#define ZM_PATH_ZMS 11 +#define ZM_COLOUR_JPEG_FILES 12 +#define ZM_ADD_JPEG_COMMENTS 13 +#define ZM_JPEG_FILE_QUALITY 14 +#define ZM_JPEG_ALARM_FILE_QUALITY 15 +#define ZM_JPEG_IMAGE_QUALITY 16 +#define ZM_JPEG_STREAM_QUALITY 17 +#define ZM_MPEG_TIMED_FRAMES 18 +#define ZM_MPEG_LIVE_FORMAT 19 +#define ZM_MPEG_REPLAY_FORMAT 20 +#define ZM_RAND_STREAM 21 +#define ZM_OPT_CAMBOZOLA 22 +#define ZM_PATH_CAMBOZOLA 23 +#define ZM_RELOAD_CAMBOZOLA 24 +#define ZM_TIMESTAMP_ON_CAPTURE 25 +#define ZM_CPU_EXTENSIONS 26 +#define ZM_FAST_IMAGE_BLENDS 27 +#define ZM_OPT_ADAPTIVE_SKIP 28 +#define ZM_BLEND_ALARMED_IMAGES 29 +#define ZM_MAX_SUSPEND_TIME 30 +#define ZM_OPT_REMOTE_CAMERAS 31 +#define ZM_NETCAM_REGEXPS 32 +#define ZM_HTTP_VERSION 33 +#define ZM_HTTP_UA 34 +#define ZM_HTTP_TIMEOUT 35 +#define ZM_MIN_RTP_PORT 36 +#define ZM_MAX_RTP_PORT 37 +#define ZM_OPT_FFMPEG 38 +#define ZM_PATH_FFMPEG 39 +#define ZM_FFMPEG_INPUT_OPTIONS 40 +#define ZM_FFMPEG_OUTPUT_OPTIONS 41 +#define ZM_FFMPEG_FORMATS 42 +#define ZM_LOG_LEVEL_SYSLOG 43 +#define ZM_LOG_LEVEL_FILE 44 +#define ZM_LOG_LEVEL_WEBLOG 45 +#define ZM_LOG_LEVEL_DATABASE 46 +#define ZM_LOG_DATABASE_LIMIT 47 +#define ZM_LOG_DEBUG 48 +#define ZM_LOG_DEBUG_TARGET 49 +#define ZM_LOG_DEBUG_LEVEL 50 +#define ZM_LOG_DEBUG_FILE 51 +#define ZM_LOG_CHECK_PERIOD 52 +#define ZM_LOG_ALERT_WAR_COUNT 53 +#define ZM_LOG_ALERT_ERR_COUNT 54 +#define ZM_LOG_ALERT_FAT_COUNT 55 +#define ZM_LOG_ALARM_WAR_COUNT 56 +#define ZM_LOG_ALARM_ERR_COUNT 57 +#define ZM_LOG_ALARM_FAT_COUNT 58 +#define ZM_RECORD_EVENT_STATS 59 +#define ZM_RECORD_DIAG_IMAGES 60 +#define ZM_DUMP_CORES 61 +#define ZM_PATH_MAP 62 +#define ZM_PATH_SOCKS 63 +#define ZM_PATH_LOGS 64 +#define ZM_PATH_SWAP 65 +#define ZM_WEB_TITLE_PREFIX 66 +#define ZM_WEB_RESIZE_CONSOLE 67 +#define ZM_WEB_POPUP_ON_ALARM 68 +#define ZM_OPT_X10 69 +#define ZM_X10_DEVICE 70 +#define ZM_X10_HOUSE_CODE 71 +#define ZM_X10_DB_RELOAD_INTERVAL 72 +#define ZM_WEB_SOUND_ON_ALARM 73 +#define ZM_WEB_ALARM_SOUND 74 +#define ZM_WEB_COMPACT_MONTAGE 75 +#define ZM_OPT_FAST_DELETE 76 +#define ZM_STRICT_VIDEO_CONFIG 77 +#define ZM_SIGNAL_CHECK_POINTS 78 +#define ZM_V4L_MULTI_BUFFER 79 +#define ZM_CAPTURES_PER_FRAME 80 +#define ZM_FILTER_RELOAD_DELAY 81 +#define ZM_FILTER_EXECUTE_INTERVAL 82 +#define ZM_OPT_UPLOAD 83 +#define ZM_UPLOAD_ARCH_FORMAT 84 +#define ZM_UPLOAD_ARCH_COMPRESS 85 +#define ZM_UPLOAD_ARCH_ANALYSE 86 +#define ZM_UPLOAD_PROTOCOL 87 +#define ZM_UPLOAD_FTP_HOST 88 +#define ZM_UPLOAD_HOST 89 +#define ZM_UPLOAD_PORT 90 +#define ZM_UPLOAD_FTP_USER 91 +#define ZM_UPLOAD_USER 92 +#define ZM_UPLOAD_FTP_PASS 93 +#define ZM_UPLOAD_PASS 94 +#define ZM_UPLOAD_FTP_LOC_DIR 95 +#define ZM_UPLOAD_LOC_DIR 96 +#define ZM_UPLOAD_FTP_REM_DIR 97 +#define ZM_UPLOAD_REM_DIR 98 +#define ZM_UPLOAD_FTP_TIMEOUT 99 +#define ZM_UPLOAD_TIMEOUT 100 +#define ZM_UPLOAD_FTP_PASSIVE 101 +#define ZM_UPLOAD_FTP_DEBUG 102 +#define ZM_UPLOAD_DEBUG 103 +#define ZM_OPT_EMAIL 104 +#define ZM_EMAIL_ADDRESS 105 +#define ZM_EMAIL_TEXT 106 +#define ZM_EMAIL_SUBJECT 107 +#define ZM_EMAIL_BODY 108 +#define ZM_OPT_MESSAGE 109 +#define ZM_MESSAGE_ADDRESS 110 +#define ZM_MESSAGE_TEXT 111 +#define ZM_MESSAGE_SUBJECT 112 +#define ZM_MESSAGE_BODY 113 +#define ZM_NEW_MAIL_MODULES 114 +#define ZM_EMAIL_HOST 115 +#define ZM_FROM_EMAIL 116 +#define ZM_URL 117 +#define ZM_MAX_RESTART_DELAY 118 +#define ZM_WATCH_CHECK_INTERVAL 119 +#define ZM_WATCH_MAX_DELAY 120 +#define ZM_RUN_AUDIT 121 +#define ZM_AUDIT_CHECK_INTERVAL 122 +#define ZM_FORCED_ALARM_SCORE 123 +#define ZM_BULK_FRAME_INTERVAL 124 +#define ZM_EVENT_CLOSE_MODE 125 +#define ZM_FORCE_CLOSE_EVENTS 126 +#define ZM_CREATE_ANALYSIS_IMAGES 127 +#define ZM_WEIGHTED_ALARM_CENTRES 128 +#define ZM_EVENT_IMAGE_DIGITS 129 +#define ZM_DEFAULT_ASPECT_RATIO 130 +#define ZM_USER_SELF_EDIT 131 +#define ZM_OPT_FRAME_SERVER 132 +#define ZM_FRAME_SOCKET_SIZE 133 +#define ZM_OPT_CONTROL 134 +#define ZM_OPT_TRIGGERS 135 +#define ZM_CHECK_FOR_UPDATES 136 +#define ZM_UPDATE_CHECK_PROXY 137 +#define ZM_SHM_KEY 138 +#define ZM_WEB_REFRESH_METHOD 139 +#define ZM_WEB_EVENT_SORT_FIELD 140 +#define ZM_WEB_EVENT_SORT_ORDER 141 +#define ZM_WEB_EVENTS_PER_PAGE 142 +#define ZM_WEB_LIST_THUMBS 143 +#define ZM_WEB_LIST_THUMB_WIDTH 144 +#define ZM_WEB_LIST_THUMB_HEIGHT 145 +#define ZM_WEB_USE_OBJECT_TAGS 146 +#define ZM_WEB_H_REFRESH_MAIN 147 +#define ZM_WEB_H_REFRESH_CYCLE 148 +#define ZM_WEB_H_REFRESH_IMAGE 149 +#define ZM_WEB_H_REFRESH_STATUS 150 +#define ZM_WEB_H_REFRESH_EVENTS 151 +#define ZM_WEB_H_CAN_STREAM 152 +#define ZM_WEB_H_STREAM_METHOD 153 +#define ZM_WEB_H_DEFAULT_SCALE 154 +#define ZM_WEB_H_DEFAULT_RATE 155 +#define ZM_WEB_H_VIDEO_BITRATE 156 +#define ZM_WEB_H_VIDEO_MAXFPS 157 +#define ZM_WEB_H_SCALE_THUMBS 158 +#define ZM_WEB_H_EVENTS_VIEW 159 +#define ZM_WEB_H_SHOW_PROGRESS 160 +#define ZM_WEB_H_AJAX_TIMEOUT 161 +#define ZM_WEB_M_REFRESH_MAIN 162 +#define ZM_WEB_M_REFRESH_CYCLE 163 +#define ZM_WEB_M_REFRESH_IMAGE 164 +#define ZM_WEB_M_REFRESH_STATUS 165 +#define ZM_WEB_M_REFRESH_EVENTS 166 +#define ZM_WEB_M_CAN_STREAM 167 +#define ZM_WEB_M_STREAM_METHOD 168 +#define ZM_WEB_M_DEFAULT_SCALE 169 +#define ZM_WEB_M_DEFAULT_RATE 170 +#define ZM_WEB_M_VIDEO_BITRATE 171 +#define ZM_WEB_M_VIDEO_MAXFPS 172 +#define ZM_WEB_M_SCALE_THUMBS 173 +#define ZM_WEB_M_EVENTS_VIEW 174 +#define ZM_WEB_M_SHOW_PROGRESS 175 +#define ZM_WEB_M_AJAX_TIMEOUT 176 +#define ZM_WEB_L_REFRESH_MAIN 177 +#define ZM_WEB_L_REFRESH_CYCLE 178 +#define ZM_WEB_L_REFRESH_IMAGE 179 +#define ZM_WEB_L_REFRESH_STATUS 180 +#define ZM_WEB_L_REFRESH_EVENTS 181 +#define ZM_WEB_L_CAN_STREAM 182 +#define ZM_WEB_L_STREAM_METHOD 183 +#define ZM_WEB_L_DEFAULT_SCALE 184 +#define ZM_WEB_L_DEFAULT_RATE 185 +#define ZM_WEB_L_VIDEO_BITRATE 186 +#define ZM_WEB_L_VIDEO_MAXFPS 187 +#define ZM_WEB_L_SCALE_THUMBS 188 +#define ZM_WEB_L_EVENTS_VIEW 189 +#define ZM_WEB_L_SHOW_PROGRESS 190 +#define ZM_WEB_L_AJAX_TIMEOUT 191 +#define ZM_WEB_P_CAN_STREAM 192 +#define ZM_WEB_P_STREAM_METHOD 193 +#define ZM_WEB_P_DEFAULT_SCALE 194 +#define ZM_WEB_P_DEFAULT_RATE 195 +#define ZM_WEB_P_VIDEO_BITRATE 196 +#define ZM_WEB_P_VIDEO_MAXFPS 197 +#define ZM_WEB_P_SCALE_THUMBS 198 +#define ZM_WEB_P_AJAX_TIMEOUT 199 +#define ZM_DYN_LAST_VERSION 200 +#define ZM_DYN_CURR_VERSION 201 +#define ZM_DYN_DB_VERSION 202 +#define ZM_DYN_LAST_CHECK 203 +#define ZM_DYN_NEXT_REMINDER 204 +#define ZM_DYN_DONATE_REMINDER_TIME 205 +#define ZM_DYN_SHOW_DONATE_REMINDER 206 +#define ZM_EYEZM_DEBUG 207 +#define ZM_EYEZM_LOG_TO_FILE 208 +#define ZM_EYEZM_LOG_FILE 209 +#define ZM_EYEZM_EVENT_VCODEC 210 +#define ZM_EYEZM_FEED_VCODEC 211 +#define ZM_EYEZM_H264_DEFAULT_BR 212 +#define ZM_EYEZM_H264_DEFAULT_EVBR 213 +#define ZM_EYEZM_H264_TIMEOUT 214 +#define ZM_EYEZM_SEG_DURATION 215 +#define ZM_PATH_PLUGINS 216 +#define ZM_PLUGIN_EXTENSION 217 +#define ZM_PLUGINS_CONFIG_PATH 218 +#define ZM_LOAD_PLUGINS 219 +#define ZM_TURNOFF_NATIVE_ANALYSIS 220 + + +#define ZM_MAX_CFG_ID 220 + +#define ZM_CFG_DECLARE_LIST \ + const char *lang_default;\ + bool opt_use_auth;\ + const char *auth_type;\ + const char *auth_relay;\ + const char *auth_hash_secret;\ + bool auth_hash_ips;\ + bool auth_hash_logins;\ + const char *dir_events;\ + bool use_deep_storage;\ + const char *dir_images;\ + const char *dir_sounds;\ + const char *path_zms;\ + bool colour_jpeg_files;\ + bool add_jpeg_comments;\ + int jpeg_file_quality;\ + int jpeg_alarm_file_quality;\ + int jpeg_image_quality;\ + int jpeg_stream_quality;\ + bool mpeg_timed_frames;\ + const char *mpeg_live_format;\ + const char *mpeg_replay_format;\ + bool rand_stream;\ + bool opt_cambozola;\ + const char *path_cambozola;\ + int reload_cambozola;\ + bool timestamp_on_capture;\ + bool cpu_extensions;\ + bool fast_image_blends;\ + bool opt_adaptive_skip;\ + bool blend_alarmed_images;\ + int max_suspend_time;\ + bool opt_remote_cameras;\ + bool netcam_regexps;\ + const char *http_version;\ + const char *http_ua;\ + int http_timeout;\ + int min_rtp_port;\ + int max_rtp_port;\ + bool opt_ffmpeg;\ + const char *path_ffmpeg;\ + const char *ffmpeg_input_options;\ + const char *ffmpeg_output_options;\ + const char *ffmpeg_formats;\ + int log_level_syslog;\ + int log_level_file;\ + int log_level_weblog;\ + int log_level_database;\ + const char *log_database_limit;\ + bool log_debug;\ + const char *log_debug_target;\ + int log_debug_level;\ + const char *log_debug_file;\ + int log_check_period;\ + int log_alert_war_count;\ + int log_alert_err_count;\ + int log_alert_fat_count;\ + int log_alarm_war_count;\ + int log_alarm_err_count;\ + int log_alarm_fat_count;\ + bool record_event_stats;\ + bool record_diag_images;\ + bool dump_cores;\ + const char *path_map;\ + const char *path_socks;\ + const char *path_logs;\ + const char *path_swap;\ + const char *web_title_prefix;\ + bool web_resize_console;\ + bool web_popup_on_alarm;\ + bool opt_x10;\ + const char *x10_device;\ + const char *x10_house_code;\ + int x10_db_reload_interval;\ + bool web_sound_on_alarm;\ + const char *web_alarm_sound;\ + bool web_compact_montage;\ + bool opt_fast_delete;\ + bool strict_video_config;\ + int signal_check_points;\ + bool v4l_multi_buffer;\ + int captures_per_frame;\ + int filter_reload_delay;\ + int filter_execute_interval;\ + bool opt_upload;\ + const char *upload_arch_format;\ + bool upload_arch_compress;\ + bool upload_arch_analyse;\ + const char *upload_protocol;\ + const char *upload_ftp_host;\ + const char *upload_host;\ + int upload_port;\ + const char *upload_ftp_user;\ + const char *upload_user;\ + const char *upload_ftp_pass;\ + const char *upload_pass;\ + const char *upload_ftp_loc_dir;\ + const char *upload_loc_dir;\ + const char *upload_ftp_rem_dir;\ + const char *upload_rem_dir;\ + int upload_ftp_timeout;\ + int upload_timeout;\ + bool upload_ftp_passive;\ + bool upload_ftp_debug;\ + bool upload_debug;\ + bool opt_email;\ + const char *email_address;\ + const char *email_text;\ + const char *email_subject;\ + const char *email_body;\ + bool opt_message;\ + const char *message_address;\ + const char *message_text;\ + const char *message_subject;\ + const char *message_body;\ + bool new_mail_modules;\ + const char *email_host;\ + const char *from_email;\ + const char *url;\ + int max_restart_delay;\ + int watch_check_interval;\ + double watch_max_delay;\ + bool run_audit;\ + int audit_check_interval;\ + int forced_alarm_score;\ + int bulk_frame_interval;\ + const char *event_close_mode;\ + bool force_close_events;\ + bool create_analysis_images;\ + bool weighted_alarm_centres;\ + int event_image_digits;\ + const char *default_aspect_ratio;\ + bool user_self_edit;\ + bool opt_frame_server;\ + int frame_socket_size;\ + bool opt_control;\ + bool opt_triggers;\ + bool check_for_updates;\ + const char *update_check_proxy;\ + int shm_key;\ + const char *web_refresh_method;\ + const char *web_event_sort_field;\ + const char *web_event_sort_order;\ + int web_events_per_page;\ + bool web_list_thumbs;\ + int web_list_thumb_width;\ + int web_list_thumb_height;\ + bool web_use_object_tags;\ + int web_h_refresh_main;\ + int web_h_refresh_cycle;\ + int web_h_refresh_image;\ + int web_h_refresh_status;\ + int web_h_refresh_events;\ + const char *web_h_can_stream;\ + const char *web_h_stream_method;\ + int web_h_default_scale;\ + int web_h_default_rate;\ + int web_h_video_bitrate;\ + int web_h_video_maxfps;\ + bool web_h_scale_thumbs;\ + const char *web_h_events_view;\ + bool web_h_show_progress;\ + int web_h_ajax_timeout;\ + int web_m_refresh_main;\ + int web_m_refresh_cycle;\ + int web_m_refresh_image;\ + int web_m_refresh_status;\ + int web_m_refresh_events;\ + const char *web_m_can_stream;\ + const char *web_m_stream_method;\ + int web_m_default_scale;\ + int web_m_default_rate;\ + int web_m_video_bitrate;\ + int web_m_video_maxfps;\ + bool web_m_scale_thumbs;\ + const char *web_m_events_view;\ + bool web_m_show_progress;\ + int web_m_ajax_timeout;\ + int web_l_refresh_main;\ + int web_l_refresh_cycle;\ + int web_l_refresh_image;\ + int web_l_refresh_status;\ + int web_l_refresh_events;\ + const char *web_l_can_stream;\ + const char *web_l_stream_method;\ + int web_l_default_scale;\ + int web_l_default_rate;\ + int web_l_video_bitrate;\ + int web_l_video_maxfps;\ + bool web_l_scale_thumbs;\ + const char *web_l_events_view;\ + bool web_l_show_progress;\ + int web_l_ajax_timeout;\ + const char *web_p_can_stream;\ + const char *web_p_stream_method;\ + int web_p_default_scale;\ + int web_p_default_rate;\ + int web_p_video_bitrate;\ + int web_p_video_maxfps;\ + bool web_p_scale_thumbs;\ + int web_p_ajax_timeout;\ + const char *dyn_last_version;\ + const char *dyn_curr_version;\ + const char *dyn_db_version;\ + int dyn_last_check;\ + const char *dyn_next_reminder;\ + int dyn_donate_reminder_time;\ + bool dyn_show_donate_reminder;\ + bool eyezm_debug;\ + bool eyezm_log_to_file;\ + const char *eyezm_log_file;\ + const char *eyezm_event_vcodec;\ + const char *eyezm_feed_vcodec;\ + const char *eyezm_h264_default_br;\ + const char *eyezm_h264_default_evbr;\ + const char *eyezm_h264_timeout;\ + const char *eyezm_seg_duration;\ + const char *path_plugins;\ + const char *plugin_extension;\ + const char *plugins_config_path;\ + bool load_plugins;\ + bool turnoff_native_analysis;\ + + +#define ZM_CFG_ASSIGN_LIST \ + lang_default = (const char *)config.Item( ZM_LANG_DEFAULT );\ + opt_use_auth = (bool)config.Item( ZM_OPT_USE_AUTH );\ + auth_type = (const char *)config.Item( ZM_AUTH_TYPE );\ + auth_relay = (const char *)config.Item( ZM_AUTH_RELAY );\ + auth_hash_secret = (const char *)config.Item( ZM_AUTH_HASH_SECRET );\ + auth_hash_ips = (bool)config.Item( ZM_AUTH_HASH_IPS );\ + auth_hash_logins = (bool)config.Item( ZM_AUTH_HASH_LOGINS );\ + dir_events = (const char *)config.Item( ZM_DIR_EVENTS );\ + use_deep_storage = (bool)config.Item( ZM_USE_DEEP_STORAGE );\ + dir_images = (const char *)config.Item( ZM_DIR_IMAGES );\ + dir_sounds = (const char *)config.Item( ZM_DIR_SOUNDS );\ + path_zms = (const char *)config.Item( ZM_PATH_ZMS );\ + colour_jpeg_files = (bool)config.Item( ZM_COLOUR_JPEG_FILES );\ + add_jpeg_comments = (bool)config.Item( ZM_ADD_JPEG_COMMENTS );\ + jpeg_file_quality = (int)config.Item( ZM_JPEG_FILE_QUALITY );\ + jpeg_alarm_file_quality = (int)config.Item( ZM_JPEG_ALARM_FILE_QUALITY );\ + jpeg_image_quality = (int)config.Item( ZM_JPEG_IMAGE_QUALITY );\ + jpeg_stream_quality = (int)config.Item( ZM_JPEG_STREAM_QUALITY );\ + mpeg_timed_frames = (bool)config.Item( ZM_MPEG_TIMED_FRAMES );\ + mpeg_live_format = (const char *)config.Item( ZM_MPEG_LIVE_FORMAT );\ + mpeg_replay_format = (const char *)config.Item( ZM_MPEG_REPLAY_FORMAT );\ + rand_stream = (bool)config.Item( ZM_RAND_STREAM );\ + opt_cambozola = (bool)config.Item( ZM_OPT_CAMBOZOLA );\ + path_cambozola = (const char *)config.Item( ZM_PATH_CAMBOZOLA );\ + reload_cambozola = (int)config.Item( ZM_RELOAD_CAMBOZOLA );\ + timestamp_on_capture = (bool)config.Item( ZM_TIMESTAMP_ON_CAPTURE );\ + cpu_extensions = (bool)config.Item( ZM_CPU_EXTENSIONS );\ + fast_image_blends = (bool)config.Item( ZM_FAST_IMAGE_BLENDS );\ + opt_adaptive_skip = (bool)config.Item( ZM_OPT_ADAPTIVE_SKIP );\ + blend_alarmed_images = (bool)config.Item( ZM_BLEND_ALARMED_IMAGES );\ + max_suspend_time = (int)config.Item( ZM_MAX_SUSPEND_TIME );\ + opt_remote_cameras = (bool)config.Item( ZM_OPT_REMOTE_CAMERAS );\ + netcam_regexps = (bool)config.Item( ZM_NETCAM_REGEXPS );\ + http_version = (const char *)config.Item( ZM_HTTP_VERSION );\ + http_ua = (const char *)config.Item( ZM_HTTP_UA );\ + http_timeout = (int)config.Item( ZM_HTTP_TIMEOUT );\ + min_rtp_port = (int)config.Item( ZM_MIN_RTP_PORT );\ + max_rtp_port = (int)config.Item( ZM_MAX_RTP_PORT );\ + opt_ffmpeg = (bool)config.Item( ZM_OPT_FFMPEG );\ + path_ffmpeg = (const char *)config.Item( ZM_PATH_FFMPEG );\ + ffmpeg_input_options = (const char *)config.Item( ZM_FFMPEG_INPUT_OPTIONS );\ + ffmpeg_output_options = (const char *)config.Item( ZM_FFMPEG_OUTPUT_OPTIONS );\ + ffmpeg_formats = (const char *)config.Item( ZM_FFMPEG_FORMATS );\ + log_level_syslog = (int)config.Item( ZM_LOG_LEVEL_SYSLOG );\ + log_level_file = (int)config.Item( ZM_LOG_LEVEL_FILE );\ + log_level_weblog = (int)config.Item( ZM_LOG_LEVEL_WEBLOG );\ + log_level_database = (int)config.Item( ZM_LOG_LEVEL_DATABASE );\ + log_database_limit = (const char *)config.Item( ZM_LOG_DATABASE_LIMIT );\ + log_debug = (bool)config.Item( ZM_LOG_DEBUG );\ + log_debug_target = (const char *)config.Item( ZM_LOG_DEBUG_TARGET );\ + log_debug_level = (int)config.Item( ZM_LOG_DEBUG_LEVEL );\ + log_debug_file = (const char *)config.Item( ZM_LOG_DEBUG_FILE );\ + log_check_period = (int)config.Item( ZM_LOG_CHECK_PERIOD );\ + log_alert_war_count = (int)config.Item( ZM_LOG_ALERT_WAR_COUNT );\ + log_alert_err_count = (int)config.Item( ZM_LOG_ALERT_ERR_COUNT );\ + log_alert_fat_count = (int)config.Item( ZM_LOG_ALERT_FAT_COUNT );\ + log_alarm_war_count = (int)config.Item( ZM_LOG_ALARM_WAR_COUNT );\ + log_alarm_err_count = (int)config.Item( ZM_LOG_ALARM_ERR_COUNT );\ + log_alarm_fat_count = (int)config.Item( ZM_LOG_ALARM_FAT_COUNT );\ + record_event_stats = (bool)config.Item( ZM_RECORD_EVENT_STATS );\ + record_diag_images = (bool)config.Item( ZM_RECORD_DIAG_IMAGES );\ + dump_cores = (bool)config.Item( ZM_DUMP_CORES );\ + path_map = (const char *)config.Item( ZM_PATH_MAP );\ + path_socks = (const char *)config.Item( ZM_PATH_SOCKS );\ + path_logs = (const char *)config.Item( ZM_PATH_LOGS );\ + path_swap = (const char *)config.Item( ZM_PATH_SWAP );\ + web_title_prefix = (const char *)config.Item( ZM_WEB_TITLE_PREFIX );\ + web_resize_console = (bool)config.Item( ZM_WEB_RESIZE_CONSOLE );\ + web_popup_on_alarm = (bool)config.Item( ZM_WEB_POPUP_ON_ALARM );\ + opt_x10 = (bool)config.Item( ZM_OPT_X10 );\ + x10_device = (const char *)config.Item( ZM_X10_DEVICE );\ + x10_house_code = (const char *)config.Item( ZM_X10_HOUSE_CODE );\ + x10_db_reload_interval = (int)config.Item( ZM_X10_DB_RELOAD_INTERVAL );\ + web_sound_on_alarm = (bool)config.Item( ZM_WEB_SOUND_ON_ALARM );\ + web_alarm_sound = (const char *)config.Item( ZM_WEB_ALARM_SOUND );\ + web_compact_montage = (bool)config.Item( ZM_WEB_COMPACT_MONTAGE );\ + opt_fast_delete = (bool)config.Item( ZM_OPT_FAST_DELETE );\ + strict_video_config = (bool)config.Item( ZM_STRICT_VIDEO_CONFIG );\ + signal_check_points = (int)config.Item( ZM_SIGNAL_CHECK_POINTS );\ + v4l_multi_buffer = (bool)config.Item( ZM_V4L_MULTI_BUFFER );\ + captures_per_frame = (int)config.Item( ZM_CAPTURES_PER_FRAME );\ + filter_reload_delay = (int)config.Item( ZM_FILTER_RELOAD_DELAY );\ + filter_execute_interval = (int)config.Item( ZM_FILTER_EXECUTE_INTERVAL );\ + opt_upload = (bool)config.Item( ZM_OPT_UPLOAD );\ + upload_arch_format = (const char *)config.Item( ZM_UPLOAD_ARCH_FORMAT );\ + upload_arch_compress = (bool)config.Item( ZM_UPLOAD_ARCH_COMPRESS );\ + upload_arch_analyse = (bool)config.Item( ZM_UPLOAD_ARCH_ANALYSE );\ + upload_protocol = (const char *)config.Item( ZM_UPLOAD_PROTOCOL );\ + upload_ftp_host = (const char *)config.Item( ZM_UPLOAD_FTP_HOST );\ + upload_host = (const char *)config.Item( ZM_UPLOAD_HOST );\ + upload_port = (int)config.Item( ZM_UPLOAD_PORT );\ + upload_ftp_user = (const char *)config.Item( ZM_UPLOAD_FTP_USER );\ + upload_user = (const char *)config.Item( ZM_UPLOAD_USER );\ + upload_ftp_pass = (const char *)config.Item( ZM_UPLOAD_FTP_PASS );\ + upload_pass = (const char *)config.Item( ZM_UPLOAD_PASS );\ + upload_ftp_loc_dir = (const char *)config.Item( ZM_UPLOAD_FTP_LOC_DIR );\ + upload_loc_dir = (const char *)config.Item( ZM_UPLOAD_LOC_DIR );\ + upload_ftp_rem_dir = (const char *)config.Item( ZM_UPLOAD_FTP_REM_DIR );\ + upload_rem_dir = (const char *)config.Item( ZM_UPLOAD_REM_DIR );\ + upload_ftp_timeout = (int)config.Item( ZM_UPLOAD_FTP_TIMEOUT );\ + upload_timeout = (int)config.Item( ZM_UPLOAD_TIMEOUT );\ + upload_ftp_passive = (bool)config.Item( ZM_UPLOAD_FTP_PASSIVE );\ + upload_ftp_debug = (bool)config.Item( ZM_UPLOAD_FTP_DEBUG );\ + upload_debug = (bool)config.Item( ZM_UPLOAD_DEBUG );\ + opt_email = (bool)config.Item( ZM_OPT_EMAIL );\ + email_address = (const char *)config.Item( ZM_EMAIL_ADDRESS );\ + email_text = (const char *)config.Item( ZM_EMAIL_TEXT );\ + email_subject = (const char *)config.Item( ZM_EMAIL_SUBJECT );\ + email_body = (const char *)config.Item( ZM_EMAIL_BODY );\ + opt_message = (bool)config.Item( ZM_OPT_MESSAGE );\ + message_address = (const char *)config.Item( ZM_MESSAGE_ADDRESS );\ + message_text = (const char *)config.Item( ZM_MESSAGE_TEXT );\ + message_subject = (const char *)config.Item( ZM_MESSAGE_SUBJECT );\ + message_body = (const char *)config.Item( ZM_MESSAGE_BODY );\ + new_mail_modules = (bool)config.Item( ZM_NEW_MAIL_MODULES );\ + email_host = (const char *)config.Item( ZM_EMAIL_HOST );\ + from_email = (const char *)config.Item( ZM_FROM_EMAIL );\ + url = (const char *)config.Item( ZM_URL );\ + max_restart_delay = (int)config.Item( ZM_MAX_RESTART_DELAY );\ + watch_check_interval = (int)config.Item( ZM_WATCH_CHECK_INTERVAL );\ + watch_max_delay = (double) config.Item( ZM_WATCH_MAX_DELAY );\ + run_audit = (bool)config.Item( ZM_RUN_AUDIT );\ + audit_check_interval = (int)config.Item( ZM_AUDIT_CHECK_INTERVAL );\ + forced_alarm_score = (int)config.Item( ZM_FORCED_ALARM_SCORE );\ + bulk_frame_interval = (int)config.Item( ZM_BULK_FRAME_INTERVAL );\ + event_close_mode = (const char *)config.Item( ZM_EVENT_CLOSE_MODE );\ + force_close_events = (bool)config.Item( ZM_FORCE_CLOSE_EVENTS );\ + create_analysis_images = (bool)config.Item( ZM_CREATE_ANALYSIS_IMAGES );\ + weighted_alarm_centres = (bool)config.Item( ZM_WEIGHTED_ALARM_CENTRES );\ + event_image_digits = (int)config.Item( ZM_EVENT_IMAGE_DIGITS );\ + default_aspect_ratio = (const char *)config.Item( ZM_DEFAULT_ASPECT_RATIO );\ + user_self_edit = (bool)config.Item( ZM_USER_SELF_EDIT );\ + opt_frame_server = (bool)config.Item( ZM_OPT_FRAME_SERVER );\ + frame_socket_size = (int)config.Item( ZM_FRAME_SOCKET_SIZE );\ + opt_control = (bool)config.Item( ZM_OPT_CONTROL );\ + opt_triggers = (bool)config.Item( ZM_OPT_TRIGGERS );\ + check_for_updates = (bool)config.Item( ZM_CHECK_FOR_UPDATES );\ + update_check_proxy = (const char *)config.Item( ZM_UPDATE_CHECK_PROXY );\ + shm_key = (int)config.Item( ZM_SHM_KEY );\ + web_refresh_method = (const char *)config.Item( ZM_WEB_REFRESH_METHOD );\ + web_event_sort_field = (const char *)config.Item( ZM_WEB_EVENT_SORT_FIELD );\ + web_event_sort_order = (const char *)config.Item( ZM_WEB_EVENT_SORT_ORDER );\ + web_events_per_page = (int)config.Item( ZM_WEB_EVENTS_PER_PAGE );\ + web_list_thumbs = (bool)config.Item( ZM_WEB_LIST_THUMBS );\ + web_list_thumb_width = (int)config.Item( ZM_WEB_LIST_THUMB_WIDTH );\ + web_list_thumb_height = (int)config.Item( ZM_WEB_LIST_THUMB_HEIGHT );\ + web_use_object_tags = (bool)config.Item( ZM_WEB_USE_OBJECT_TAGS );\ + web_h_refresh_main = (int)config.Item( ZM_WEB_H_REFRESH_MAIN );\ + web_h_refresh_cycle = (int)config.Item( ZM_WEB_H_REFRESH_CYCLE );\ + web_h_refresh_image = (int)config.Item( ZM_WEB_H_REFRESH_IMAGE );\ + web_h_refresh_status = (int)config.Item( ZM_WEB_H_REFRESH_STATUS );\ + web_h_refresh_events = (int)config.Item( ZM_WEB_H_REFRESH_EVENTS );\ + web_h_can_stream = (const char *)config.Item( ZM_WEB_H_CAN_STREAM );\ + web_h_stream_method = (const char *)config.Item( ZM_WEB_H_STREAM_METHOD );\ + web_h_default_scale = (int)config.Item( ZM_WEB_H_DEFAULT_SCALE );\ + web_h_default_rate = (int)config.Item( ZM_WEB_H_DEFAULT_RATE );\ + web_h_video_bitrate = (int)config.Item( ZM_WEB_H_VIDEO_BITRATE );\ + web_h_video_maxfps = (int)config.Item( ZM_WEB_H_VIDEO_MAXFPS );\ + web_h_scale_thumbs = (bool)config.Item( ZM_WEB_H_SCALE_THUMBS );\ + web_h_events_view = (const char *)config.Item( ZM_WEB_H_EVENTS_VIEW );\ + web_h_show_progress = (bool)config.Item( ZM_WEB_H_SHOW_PROGRESS );\ + web_h_ajax_timeout = (int)config.Item( ZM_WEB_H_AJAX_TIMEOUT );\ + web_m_refresh_main = (int)config.Item( ZM_WEB_M_REFRESH_MAIN );\ + web_m_refresh_cycle = (int)config.Item( ZM_WEB_M_REFRESH_CYCLE );\ + web_m_refresh_image = (int)config.Item( ZM_WEB_M_REFRESH_IMAGE );\ + web_m_refresh_status = (int)config.Item( ZM_WEB_M_REFRESH_STATUS );\ + web_m_refresh_events = (int)config.Item( ZM_WEB_M_REFRESH_EVENTS );\ + web_m_can_stream = (const char *)config.Item( ZM_WEB_M_CAN_STREAM );\ + web_m_stream_method = (const char *)config.Item( ZM_WEB_M_STREAM_METHOD );\ + web_m_default_scale = (int)config.Item( ZM_WEB_M_DEFAULT_SCALE );\ + web_m_default_rate = (int)config.Item( ZM_WEB_M_DEFAULT_RATE );\ + web_m_video_bitrate = (int)config.Item( ZM_WEB_M_VIDEO_BITRATE );\ + web_m_video_maxfps = (int)config.Item( ZM_WEB_M_VIDEO_MAXFPS );\ + web_m_scale_thumbs = (bool)config.Item( ZM_WEB_M_SCALE_THUMBS );\ + web_m_events_view = (const char *)config.Item( ZM_WEB_M_EVENTS_VIEW );\ + web_m_show_progress = (bool)config.Item( ZM_WEB_M_SHOW_PROGRESS );\ + web_m_ajax_timeout = (int)config.Item( ZM_WEB_M_AJAX_TIMEOUT );\ + web_l_refresh_main = (int)config.Item( ZM_WEB_L_REFRESH_MAIN );\ + web_l_refresh_cycle = (int)config.Item( ZM_WEB_L_REFRESH_CYCLE );\ + web_l_refresh_image = (int)config.Item( ZM_WEB_L_REFRESH_IMAGE );\ + web_l_refresh_status = (int)config.Item( ZM_WEB_L_REFRESH_STATUS );\ + web_l_refresh_events = (int)config.Item( ZM_WEB_L_REFRESH_EVENTS );\ + web_l_can_stream = (const char *)config.Item( ZM_WEB_L_CAN_STREAM );\ + web_l_stream_method = (const char *)config.Item( ZM_WEB_L_STREAM_METHOD );\ + web_l_default_scale = (int)config.Item( ZM_WEB_L_DEFAULT_SCALE );\ + web_l_default_rate = (int)config.Item( ZM_WEB_L_DEFAULT_RATE );\ + web_l_video_bitrate = (int)config.Item( ZM_WEB_L_VIDEO_BITRATE );\ + web_l_video_maxfps = (int)config.Item( ZM_WEB_L_VIDEO_MAXFPS );\ + web_l_scale_thumbs = (bool)config.Item( ZM_WEB_L_SCALE_THUMBS );\ + web_l_events_view = (const char *)config.Item( ZM_WEB_L_EVENTS_VIEW );\ + web_l_show_progress = (bool)config.Item( ZM_WEB_L_SHOW_PROGRESS );\ + web_l_ajax_timeout = (int)config.Item( ZM_WEB_L_AJAX_TIMEOUT );\ + web_p_can_stream = (const char *)config.Item( ZM_WEB_P_CAN_STREAM );\ + web_p_stream_method = (const char *)config.Item( ZM_WEB_P_STREAM_METHOD );\ + web_p_default_scale = (int)config.Item( ZM_WEB_P_DEFAULT_SCALE );\ + web_p_default_rate = (int)config.Item( ZM_WEB_P_DEFAULT_RATE );\ + web_p_video_bitrate = (int)config.Item( ZM_WEB_P_VIDEO_BITRATE );\ + web_p_video_maxfps = (int)config.Item( ZM_WEB_P_VIDEO_MAXFPS );\ + web_p_scale_thumbs = (bool)config.Item( ZM_WEB_P_SCALE_THUMBS );\ + web_p_ajax_timeout = (int)config.Item( ZM_WEB_P_AJAX_TIMEOUT );\ + dyn_last_version = (const char *)config.Item( ZM_DYN_LAST_VERSION );\ + dyn_curr_version = (const char *)config.Item( ZM_DYN_CURR_VERSION );\ + dyn_db_version = (const char *)config.Item( ZM_DYN_DB_VERSION );\ + dyn_last_check = (int)config.Item( ZM_DYN_LAST_CHECK );\ + dyn_next_reminder = (const char *)config.Item( ZM_DYN_NEXT_REMINDER );\ + dyn_donate_reminder_time = (int)config.Item( ZM_DYN_DONATE_REMINDER_TIME );\ + dyn_show_donate_reminder = (bool)config.Item( ZM_DYN_SHOW_DONATE_REMINDER );\ + eyezm_debug = (bool)config.Item( ZM_EYEZM_DEBUG );\ + eyezm_log_to_file = (bool)config.Item( ZM_EYEZM_LOG_TO_FILE );\ + eyezm_log_file = (const char *)config.Item( ZM_EYEZM_LOG_FILE );\ + eyezm_event_vcodec = (const char *)config.Item( ZM_EYEZM_EVENT_VCODEC );\ + eyezm_feed_vcodec = (const char *)config.Item( ZM_EYEZM_FEED_VCODEC );\ + eyezm_h264_default_br = (const char *)config.Item( ZM_EYEZM_H264_DEFAULT_BR );\ + eyezm_h264_default_evbr = (const char *)config.Item( ZM_EYEZM_H264_DEFAULT_EVBR );\ + eyezm_h264_timeout = (const char *)config.Item( ZM_EYEZM_H264_TIMEOUT );\ + eyezm_seg_duration = (const char *)config.Item( ZM_EYEZM_SEG_DURATION );\ + path_plugins = (const char *)config.Item( ZM_PATH_PLUGINS );\ + plugin_extension = (const char *)config.Item( ZM_PLUGIN_EXTENSION );\ + plugins_config_path = (const char *)config.Item( ZM_PLUGINS_CONFIG_PATH );\ + load_plugins = (bool)config.Item( ZM_LOAD_PLUGINS );\ + turnoff_native_analysis = (bool)config.Item( ZM_TURNOFF_NATIVE_ANALYSIS );\ + + diff --git a/src/zm_coord.cpp b/src/zm_coord.cpp new file mode 100644 index 000000000..cef188b63 --- /dev/null +++ b/src/zm_coord.cpp @@ -0,0 +1,23 @@ +// +// ZoneMinder Coordinate Class Implementation, $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. +// + +#include "zm.h" +#include "zm_coord.h" + +// This section deliberately left blank diff --git a/src/zm_coord.h b/src/zm_coord.h new file mode 100644 index 000000000..6a6620529 --- /dev/null +++ b/src/zm_coord.h @@ -0,0 +1,67 @@ +// +// ZoneMinder Coordinate Class Interface, $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. +// + +#ifndef ZM_COORD_H +#define ZM_COORD_H + +#include "zm.h" + +// +// Class used for storing an x,y pair, i.e. a coordinate +// +class Coord +{ +private: + int x, y; + +public: + inline Coord() : x(0), y(0) + { + } + inline Coord( int p_x, int p_y ) : x(p_x), y(p_y) + { + } + inline Coord( const Coord &p_coord ) : x(p_coord.x), y(p_coord.y) + { + } + inline int &X() { return( x ); } + inline const int &X() const { return( x ); } + inline int &Y() { return( y ); } + inline const int &Y() const { return( y ); } + + inline static Coord Range( const Coord &coord1, const Coord &coord2 ) + { + Coord result( (coord1.x-coord2.x)+1, (coord1.y-coord2.y)+1 ); + return( result ); + } + + inline bool operator==( const Coord &coord ) { return( x == coord.x && y == coord.y ); } + inline bool operator!=( const Coord &coord ) { return( x != coord.x || y != coord.y ); } + inline bool operator>( const Coord &coord ) { return( x > coord.x && y > coord.y ); } + inline bool operator>=( const Coord &coord ) { return( !(operator<(coord)) ); } + inline bool operator<( const Coord &coord ) { return( x < coord.x && y < coord.y ); } + inline bool operator<=( const Coord &coord ) { return( !(operator>(coord)) ); } + inline Coord &operator+=( const Coord &coord ) { x += coord.x; y += coord.y; return( *this ); } + inline Coord &operator-=( const Coord &coord ) { x -= coord.x; y -= coord.y; return( *this ); } + + inline friend Coord operator+( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result += coord2; return( result ); } + inline friend Coord operator-( const Coord &coord1, const Coord &coord2 ) { Coord result( coord1 ); result -= coord2; return( result ); } +}; + +#endif // ZM_COORD_H diff --git a/src/zm_db.cpp b/src/zm_db.cpp new file mode 100644 index 000000000..26a33d6f5 --- /dev/null +++ b/src/zm_db.cpp @@ -0,0 +1,66 @@ +// +// ZoneMinder MySQL Implementation, $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. +// + +#include +#include + +#include "zm.h" +#include "zm_db.h" + +MYSQL dbconn; + +int zmDbConnected = false; + +void zmDbConnect() +{ + if ( !mysql_init( &dbconn ) ) + { + Error( "Can't initialise database connection: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + my_bool reconnect = 1; + if ( mysql_options( &dbconn, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &dbconn ) ); + std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); + if ( colonIndex != std::string::npos ) + { + std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); + std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); + if ( !mysql_real_connect( &dbconn, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) + { + Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + } + else + { + if ( !mysql_real_connect( &dbconn, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) + { + Error( "Can't connect to server: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + } + if ( mysql_select_db( &dbconn, staticConfig.DB_NAME.c_str() ) ) + { + Error( "Can't select database: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + zmDbConnected = true; +} + diff --git a/src/zm_db.h b/src/zm_db.h new file mode 100644 index 000000000..dda2dd30f --- /dev/null +++ b/src/zm_db.h @@ -0,0 +1,37 @@ +// +// ZoneMinder Core Interfaces, $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. +// + +#ifndef ZM_DB_H +#define ZM_DB_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif +extern MYSQL dbconn; + +extern int zmDbConnected; + +void zmDbConnect(); +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif // ZM_DB_H diff --git a/src/zm_detector.cpp b/src/zm_detector.cpp new file mode 100644 index 000000000..0ec360c66 --- /dev/null +++ b/src/zm_detector.cpp @@ -0,0 +1,200 @@ +#include "zm_detector.h" + + + +/*!\fn Detector::Detector(const Detector& source) + * \param source is the object to copy + */ +Detector::Detector(const Detector& source) + : m_sDetectionCause(source.m_sDetectionCause), + m_fMinAlarmScore(source.m_fMinAlarmScore), + m_fMaxAlarmScore(source.m_fMaxAlarmScore), + m_fImageScaleFactor(source.m_fImageScaleFactor), + m_nNewWidth(source.m_nNewWidth), + m_nNewHeight(source.m_nNewHeight), + m_sLogPrefix(source.m_sLogPrefix), + m_sConfigSectionName(source.m_sConfigSectionName) +{ + //setlogmask (LOG_UPTO (LOG_LEVEL)); + //openlog(m_sLogPrefix.c_str(), LOG_PID|LOG_CONS, LOG_USER); +} + + + +/*!\fn Detector& ImageAnalyser::Detector::operator=(const ImageAnalyser::Detector& source) + * \param source is the object to copy + */ +Detector& Detector::operator=(const Detector& source) +{ + m_sDetectionCause = source.m_sDetectionCause; + m_fMinAlarmScore = source.m_fMinAlarmScore; + m_fMaxAlarmScore = source.m_fMaxAlarmScore; + m_fImageScaleFactor = source.m_fImageScaleFactor; + m_sLogPrefix = source.m_sLogPrefix; + m_nNewWidth = source.m_nNewWidth; + m_nNewHeight = source.m_nNewHeight; + m_sConfigSectionName = source.m_sConfigSectionName; + + //setlogmask (LOG_UPTO (LOG_LEVEL)); + //openlog(m_sLogPrefix.c_str(), LOG_PID|LOG_CONS, LOG_USER); + + return *this; +} + + + +/*!\fn Detector::getDetectionCause() + * return detection cause as string + */ +string Detector::getDetectionCause() +{ + return m_sDetectionCause; +} + + + + +/*! \fn Detector::log(int nLogLevel, string sMessage) + */ +void Detector::log(int nLogLevel, string sMessage) +{ + string sMessageToLog = m_sLogPrefix + string(" : ") + sMessage; + syslog(nLogLevel, "%s", sMessageToLog.c_str()); +} + + +//Detector::~Detector() {} + + + + +/*! \fn int FaceDetectorPlugin::Detect(const Image &image, Event::StringSet &zoneSet) + * \param image is an image to detect faces on + * \param zoneSet is set of zone names (see zm_zone.h) + * \return detection score + */ +int Detector::Detect(const Image &zmImage, Zone** zones, int n_numZones, Event::StringSet &zoneSet) +{ + //log(LOG_LEVEL, "Detection invoking."); + bool alarm = false; + char szMessage[50]; + unsigned int score = 0; + + if (n_numZones <= 0) return (alarm); + + +// // Blank out all exclusion zones +// for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) +// { +// Zone *zone = zones[n_zone]; +// zone->ClearAlarm(); +// if ( !zone->IsInactive() ) +// { +// continue; +// } +// Debug( 3, "Blanking inactive zone %s", zone->Label() ); +// delta_image->Fill( RGB_BLACK, zone->GetPolygon() ); +// } + + // Check preclusive zones first + for (int n_zone = 0; n_zone < n_numZones; n_zone++) + { + Zone *zone = zones[n_zone]; + if (!zone->IsPreclusive()) + { + continue; + } + sprintf(szMessage, "Checking preclusive zone %s", zone->Label()); + log(LOG_DEBUG, szMessage); + if (checkZone(zone, &zmImage)) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score()); + log(LOG_DEBUG, szMessage); + zoneSet.insert(zone->Label()); + } + } + + if ( alarm ) + { + alarm = false; + score = 0; + } + else + { + // Find all alarm pixels in active zones + for (int n_zone = 0; n_zone < n_numZones; n_zone++) + { + Zone *zone = zones[n_zone]; + if (!zone->IsActive()) + { + continue; + } + //sprintf(szMessage, "Checking active zone %s", zone->Label()); + //log(LOG_DEBUG, szMessage); + if (checkZone(zone, &zmImage)) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score()); + log(LOG_DEBUG, szMessage); + zoneSet.insert(zone->Label()); + } + } + + if ( alarm ) + { + // Checking inclusive zones + for (int n_zone = 0; n_zone < n_numZones; n_zone++) + { + Zone *zone = zones[n_zone]; + if (!zone->IsInclusive()) + { + continue; + } + sprintf(szMessage, "Checking inclusive zone %s", zone->Label()); + log(LOG_DEBUG, szMessage); + if (checkZone(zone, &zmImage)) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score()); + log(LOG_DEBUG, szMessage); + zoneSet.insert(zone->Label()); + } + } + } + else + { + // Find all alarm pixels in exclusive zones + for (int n_zone = 0; n_zone < n_numZones; n_zone++) + { + Zone *zone = zones[n_zone]; + if (!zone->IsExclusive()) + { + continue; + } + sprintf(szMessage, "Checking exclusive zone %s", zone->Label()); + log(LOG_DEBUG, szMessage); + if (checkZone(zone, &zmImage)) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + sprintf(szMessage, "Zone is alarmed, zone score = %d", zone->Score()); + log(LOG_DEBUG, szMessage); + zoneSet.insert(zone->Label()); + } + } + } //else if(alarm) : exclusive + } //else if(alarm) + + + return(score?score:alarm); +} + + diff --git a/src/zm_detector.h b/src/zm_detector.h new file mode 100644 index 000000000..b1902577c --- /dev/null +++ b/src/zm_detector.h @@ -0,0 +1,129 @@ +#ifndef ZM_DETECTOR_H +#define ZM_DETECTOR_H + + +#include +#include +#include + +#include "zm_image.h" +#include "zm_zone.h" +#include "zm_event.h" + + + +#define DEFAULT_DETECTION_CAUSE "Object Detected" +#define DEFAULT_MIN_ALARM_SCORE 1.0 +#define DEFAULT_MAX_ALARM_SCORE 99.0 +#define DEFAULT_IMAGE_SCALE_FACTOR 1.0 + +#define DEFAULT_LOG_PREFIX "ZM PLUGIN" +#define LOG_LEVEL LOG_NOTICE +#define DEFAULT_CONFIGFILE_SECTION "libzm_vscvl_plugin" + +using namespace std; + + +//! Base class for object detectors, defined in plugins. +class Detector +{ + +public: + + //! Destructor + virtual ~Detector() { closelog(); } + + //! Default constructor + Detector() +{ + m_sLogPrefix = DEFAULT_LOG_PREFIX; + + //setlogmask (LOG_UPTO (LOG_LEVEL)); + //openlog(m_sLogPrefix.c_str(), LOG_PID|LOG_CONS, LOG_USER); + + m_sDetectionCause = DEFAULT_DETECTION_CAUSE; + m_fMinAlarmScore = DEFAULT_MIN_ALARM_SCORE; + m_fMaxAlarmScore = DEFAULT_MAX_ALARM_SCORE; + m_fImageScaleFactor = DEFAULT_IMAGE_SCALE_FACTOR; + m_sConfigSectionName = DEFAULT_CONFIGFILE_SECTION; + m_nNewWidth = 0; + m_nNewHeight = 0; +} + + //! Constructor with section name parameter. + Detector(string sPluginFileName) +{ + m_sLogPrefix = DEFAULT_LOG_PREFIX; + + char* szPluginFileName = strdup(sPluginFileName.c_str()); + + string sPluginFileNameName = string(basename(szPluginFileName)); + + size_t idx = sPluginFileNameName.rfind('.'); + + if (idx == string::npos) + m_sConfigSectionName = sPluginFileNameName; + else + m_sConfigSectionName = sPluginFileNameName.substr(0, idx); + + m_sDetectionCause = DEFAULT_DETECTION_CAUSE; + m_fMinAlarmScore = DEFAULT_MIN_ALARM_SCORE; + m_fMaxAlarmScore = DEFAULT_MAX_ALARM_SCORE; + m_fImageScaleFactor = DEFAULT_IMAGE_SCALE_FACTOR; + m_nNewWidth = 0; + m_nNewHeight = 0; +} + + //! Copy constructor + Detector(const Detector& source); + + //! Assignment operator + Detector& operator=(const Detector& source); + + //! Detect (in an image later) + int Detect(const Image &image, Zone** zones, int n_numZones, Event::StringSet &zoneSet); + + //! Load detector's parameters from a config file. + virtual void loadConfig(string sConfigFileName) = 0; + + //! Returns detection case string. + string getDetectionCause(); + +protected: + + //! Do detection inside one given zone. + virtual bool checkZone(Zone *zone, const Image *zmImage) = 0; + + //! Log messages to the SYSLOG. + void log(int, string sMessage); + + //! String to be shown as detection cause for event. + string m_sDetectionCause; + + //! Minimum score value to consider frame as to be alarmed. + double m_fMinAlarmScore; + + //! Maximum score value to consider frame as to be alarmed. + double m_fMaxAlarmScore; + + //! Maximum allowed width of frame image. + double m_fImageScaleFactor; + + //! Width of image to resize. + int m_nNewWidth; + + //! Height of image to resize. + int m_nNewHeight; +// +// //! Output stream for logging errors. +// ofstream m_outStream; + + //! String prefix for SYSLOG messages. + string m_sLogPrefix; + + //! Name of config file section to search parameters. + string m_sConfigSectionName; +}; + + +#endif // ZM_DETECTOR_H diff --git a/src/zm_event.cpp b/src/zm_event.cpp new file mode 100644 index 000000000..a43f31a66 --- /dev/null +++ b/src/zm_event.cpp @@ -0,0 +1,1457 @@ +// +// ZoneMinder Event Class Implementation, $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. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_time.h" +#include "zm_mpeg.h" +#include "zm_signal.h" +#include "zm_event.h" +#include "zm_monitor.h" + +#include "zmf.h" + +#if HAVE_SYS_SENDFILE_H +#include +#endif + +//#define USE_PREPARED_SQL 1 + +bool Event::initialised = false; +char Event::capture_file_format[PATH_MAX]; +char Event::analyse_file_format[PATH_MAX]; +char Event::general_file_format[PATH_MAX]; + +int Event::pre_alarm_count = 0; +Event::PreAlarmData Event::pre_alarm_data[MAX_PRE_ALARM_FRAMES] = { { 0 } }; + +Event::Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ) : + monitor( p_monitor ), + start_time( p_start_time ), + cause( p_cause ), + noteSetMap( p_noteSetMap ) +{ + if ( !initialised ) + Initialise(); + + std::string notes; + createNotes( notes ); + + bool untimedEvent = false; + if ( !start_time.tv_sec ) + { + untimedEvent = true; + gettimeofday( &start_time, 0 ); + } + + static char sql[ZM_SQL_MED_BUFSIZ]; + + struct tm *stime = localtime( &start_time.tv_sec ); + snprintf( sql, sizeof(sql), "insert into Events ( MonitorId, Name, StartTime, Width, Height, Cause, Notes ) values ( %d, 'New Event', from_unixtime( %ld ), %d, %d, '%s', '%s' )", monitor->Id(), start_time.tv_sec, monitor->Width(), monitor->Height(), cause.c_str(), notes.c_str() ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + id = mysql_insert_id( &dbconn ); + if ( untimedEvent ) + { + Warning( "Event %d has zero time, setting to current", id ); + } + end_time.tv_sec = 0; + frames = 0; + alarm_frames = 0; + tot_score = 0; + max_score = 0; + + if ( config.use_deep_storage ) + { + char *path_ptr = path; + path_ptr += snprintf( path_ptr, sizeof(path), "%s/%d", config.dir_events, monitor->Id() ); + + int dt_parts[6]; + dt_parts[0] = stime->tm_year-100; + dt_parts[1] = stime->tm_mon+1; + dt_parts[2] = stime->tm_mday; + dt_parts[3] = stime->tm_hour; + dt_parts[4] = stime->tm_min; + dt_parts[5] = stime->tm_sec; + + char date_path[PATH_MAX] = ""; + char time_path[PATH_MAX] = ""; + char *time_path_ptr = time_path; + for ( unsigned int i = 0; i < sizeof(dt_parts)/sizeof(*dt_parts); i++ ) + { + path_ptr += snprintf( path_ptr, sizeof(path)-(path_ptr-path), "/%02d", dt_parts[i] ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Fatal( "Can't mkdir %s: %s", path, strerror(errno)); + } + } + if ( i == 2 ) + strncpy( date_path, path, sizeof(date_path) ); + else if ( i >= 3 ) + time_path_ptr += snprintf( time_path_ptr, sizeof(time_path)-(time_path_ptr-time_path), "%s%02d", i>3?"/":"", dt_parts[i] ); + } + char id_file[PATH_MAX]; + // Create event id symlink + snprintf( id_file, sizeof(id_file), "%s/.%d", date_path, id ); + if ( symlink( time_path, id_file ) < 0 ) + Fatal( "Can't symlink %s -> %s: %s", id_file, path, strerror(errno)); + // Create empty id tag file + snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); + if ( FILE *id_fp = fopen( id_file, "w" ) ) + fclose( id_fp ); + else + Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); + } + else + { + snprintf( path, sizeof(path), "%s/%d/%d", config.dir_events, monitor->Id(), id ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't mkdir %s: %s", path, strerror(errno)); + } + } + char id_file[PATH_MAX]; + // Create empty id tag file + snprintf( id_file, sizeof(id_file), "%s/.%d", path, id ); + if ( FILE *id_fp = fopen( id_file, "w" ) ) + fclose( id_fp ); + else + Fatal( "Can't fopen %s: %s", id_file, strerror(errno)); + } + last_db_frame = 0; +} + +Event::~Event() +{ + if ( frames > last_db_frame ) + { + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); + + Debug( 1, "Adding closing frame %d to DB", frames ); + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ( %d, %d, from_unixtime( %ld ), %s%ld.%02ld )", id, frames, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + } + + static char sql[ZM_SQL_MED_BUFSIZ]; + + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, end_time, start_time, DT_PREC_2 ); + + snprintf( sql, sizeof(sql), "update Events set Name='%s%d', EndTime = from_unixtime( %ld ), Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", monitor->EventPrefix(), id, end_time.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't update event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +void Event::createNotes( std::string ¬es ) +{ + notes.clear(); + for ( StringSetMap::const_iterator mapIter = noteSetMap.begin(); mapIter != noteSetMap.end(); mapIter++ ) + { + notes += mapIter->first; + notes += ": "; + const StringSet &stringSet = mapIter->second; + for ( StringSet::const_iterator setIter = stringSet.begin(); setIter != stringSet.end(); setIter++ ) + { + if ( setIter != stringSet.begin() ) + notes += ", "; + notes += *setIter; + } + } +} + +int Event::sd = -1; + +bool Event::OpenFrameSocket( int monitor_id ) +{ + if ( sd > 0 ) + { + close( sd ); + } + + sd = socket( AF_UNIX, SOCK_STREAM, 0); + if ( sd < 0 ) + { + Error( "Can't create socket: %s", strerror(errno) ); + return( false ); + } + + int socket_buffer_size = config.frame_socket_size; + if ( socket_buffer_size > 0 ) + { + if ( setsockopt( sd, SOL_SOCKET, SO_SNDBUF, &socket_buffer_size, sizeof(socket_buffer_size) ) < 0 ) + { + Error( "Can't get socket buffer size to %d, error = %s", socket_buffer_size, strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } + } + + int flags; + if ( (flags = fcntl( sd, F_GETFL )) < 0 ) + { + Error( "Can't get socket flags, error = %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } + flags |= O_NONBLOCK; + if ( fcntl( sd, F_SETFL, flags ) < 0 ) + { + Error( "Can't set socket flags, error = %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } + + char sock_path[PATH_MAX] = ""; + snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); + + struct sockaddr_un addr; + + strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); + addr.sun_family = AF_UNIX; + + if ( connect( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) + { + Warning( "Can't connect to frame server: %s", strerror(errno) ); + close( sd ); + sd = -1; + return( false ); + } + + Debug( 1, "Opened connection to frame server" ); + return( true ); +} + +bool Event::ValidateFrameSocket( int monitor_id ) +{ + if ( sd < 0 ) + { + return( OpenFrameSocket( monitor_id ) ); + } + return( true ); +} + +bool Event::SendFrameImage( const Image *image, bool alarm_frame ) +{ + if ( !ValidateFrameSocket( monitor->Id() ) ) + { + return( false ); + } + + static int jpg_buffer_size = 0; + static unsigned char jpg_buffer[ZM_MAX_IMAGE_SIZE]; + + image->EncodeJpeg( jpg_buffer, &jpg_buffer_size, (alarm_frame&&(config.jpeg_alarm_file_quality>config.jpeg_file_quality))?config.jpeg_alarm_file_quality:config.jpeg_file_quality ); + + static FrameHeader frame_header; + + frame_header.event_id = id; + if ( config.use_deep_storage ) + frame_header.event_time = start_time.tv_sec; + frame_header.frame_id = frames; + frame_header.alarm_frame = alarm_frame; + frame_header.image_length = jpg_buffer_size; + + struct iovec iovecs[2]; + iovecs[0].iov_base = &frame_header; + iovecs[0].iov_len = sizeof(frame_header); + iovecs[1].iov_base = jpg_buffer; + iovecs[1].iov_len = jpg_buffer_size; + + ssize_t writev_size = sizeof(frame_header)+jpg_buffer_size; + ssize_t writev_result = writev( sd, iovecs, sizeof(iovecs)/sizeof(*iovecs)); + if ( writev_result != writev_size ) + { + if ( writev_result < 0 ) + { + if ( errno == EAGAIN ) + { + Warning( "Blocking write detected" ); + } + else + { + Error( "Can't write frame: %s", strerror(errno) ); + close( sd ); + sd = -1; + } + } + else + { + Error( "Incomplete frame write: %zd of %zd bytes written", writev_result, writev_size ); + close( sd ); + sd = -1; + } + return( false ); + } + Debug( 1, "Wrote frame image, %d bytes", jpg_buffer_size ); + + return( true ); +} + +bool Event::WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame ) +{ + if ( config.timestamp_on_capture ) + { + if ( !config.opt_frame_server || !SendFrameImage( image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + image->WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + image->WriteJpeg( event_file ); + } + } + else + { + Image ts_image( *image ); + monitor->TimestampImage( &ts_image, ×tamp ); + if ( !config.opt_frame_server || !SendFrameImage( &ts_image, alarm_frame) ) + { + if ( alarm_frame && (config.jpeg_alarm_file_quality > config.jpeg_file_quality) ) + ts_image.WriteJpeg( event_file, config.jpeg_alarm_file_quality ); + else + ts_image.WriteJpeg( event_file ); + } + } + return( true ); +} + +void Event::updateNotes( const StringSetMap &newNoteSetMap ) +{ + bool update = false; + + //Info( "Checking notes, %d <> %d", noteSetMap.size(), newNoteSetMap.size() ); + if ( newNoteSetMap.size() > 0 ) + { + if ( noteSetMap.size() == 0 ) + { + noteSetMap = newNoteSetMap; + update = true; + } + else + { + for ( StringSetMap::const_iterator newNoteSetMapIter = newNoteSetMap.begin(); newNoteSetMapIter != newNoteSetMap.end(); newNoteSetMapIter++ ) + { + const std::string &newNoteGroup = newNoteSetMapIter->first; + const StringSet &newNoteSet = newNoteSetMapIter->second; + //Info( "Got %d new strings", newNoteSet.size() ); + if ( newNoteSet.size() > 0 ) + { + StringSetMap::iterator noteSetMapIter = noteSetMap.find( newNoteGroup ); + if ( noteSetMapIter == noteSetMap.end() ) + { + //Info( "Can't find note group %s, copying %d strings", newNoteGroup.c_str(), newNoteSet.size() ); + noteSetMap.insert( StringSetMap::value_type( newNoteGroup, newNoteSet ) ); + update = true; + } + else + { + StringSet ¬eSet = noteSetMapIter->second; + //Info( "Found note group %s, got %d strings", newNoteGroup.c_str(), newNoteSet.size() ); + for ( StringSet::const_iterator newNoteSetIter = newNoteSet.begin(); newNoteSetIter != newNoteSet.end(); newNoteSetIter++ ) + { + const std::string &newNote = *newNoteSetIter; + StringSet::iterator noteSetIter = noteSet.find( newNote ); + if ( noteSetIter == noteSet.end() ) + { + noteSet.insert( newNote ); + update = true; + } + } + } + } + } + } + } + + if ( update ) + { + std::string notes; + createNotes( notes ); + + Debug( 2, "Updating notes for event %d, '%s'", id, notes.c_str() ); + static char sql[ZM_SQL_MED_BUFSIZ]; +#if USE_PREPARED_SQL + static MYSQL_STMT *stmt = 0; + + char notesStr[ZM_SQL_MED_BUFSIZ] = ""; + unsigned long notesLen = 0; + + if ( !stmt ) + { + const char *sql = "update Events set Notes = ? where Id = ?"; + + stmt = mysql_stmt_init( &dbconn ); + if ( mysql_stmt_prepare( stmt, sql, strlen(sql) ) ) + { + Fatal( "Unable to prepare sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } + + /* Get the parameter count from the statement */ + if ( mysql_stmt_param_count( stmt ) != 2 ) + { + Fatal( "Unexpected parameter count %ld in sql '%s'", mysql_stmt_param_count( stmt ), sql ); + } + + MYSQL_BIND bind[2]; + memset(bind, 0, sizeof(bind)); + + /* STRING PARAM */ + bind[0].buffer_type = MYSQL_TYPE_STRING; + bind[0].buffer = (char *)notesStr; + bind[0].buffer_length = sizeof(notesStr); + bind[0].is_null = 0; + bind[0].length = ¬esLen; + + bind[1].buffer_type= MYSQL_TYPE_LONG; + bind[1].buffer= (char *)&id; + bind[1].is_null= 0; + bind[1].length= 0; + + /* Bind the buffers */ + if ( mysql_stmt_bind_param( stmt, bind ) ) + { + Fatal( "Unable to bind sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } + } + + strncpy( notesStr, notes.c_str(), sizeof(notesStr) ); + notesLen = notes.length(); + + if ( mysql_stmt_execute( stmt ) ) + { + Fatal( "Unable to execute sql '%s': %s", sql, mysql_stmt_error(stmt) ); + } +#else + static char escapedNotes[ZM_SQL_MED_BUFSIZ]; + + mysql_real_escape_string( &dbconn, escapedNotes, notes.c_str(), notes.length() ); + + snprintf( sql, sizeof(sql), "update Events set Notes = '%s' where Id = %d", escapedNotes, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event: %s", mysql_error( &dbconn ) ); + } +#endif + } +} + +void Event::AddFrames( int n_frames, Image **images, struct timeval **timestamps ) +{ + static char sql[ZM_SQL_LGE_BUFSIZ]; + strncpy( sql, "insert into Frames ( EventId, FrameId, TimeStamp, Delta ) values ", sizeof(sql) ); + int frameCount = 0; + for ( int i = 0; i < n_frames; i++ ) + { + if ( !timestamps[i]->tv_sec ) + { + Debug( 1, "Not adding pre-capture frame %d, zero timestamp", i ); + continue; + } + + frames++; + + static char event_file[PATH_MAX]; + snprintf( event_file, sizeof(event_file), capture_file_format, path, frames ); + + Debug( 1, "Writing pre-capture frame %d", frames ); + WriteFrameImage( images[i], *(timestamps[i]), event_file ); + + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, *(timestamps[i]), start_time, DT_PREC_2 ); + + int sql_len = strlen(sql); + snprintf( sql+sql_len, sizeof(sql)-sql_len, "( %d, %d, from_unixtime(%ld), %s%ld.%02ld ), ", id, frames, timestamps[i]->tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec ); + + frameCount++; + } + + if ( frameCount ) + { + Debug( 1, "Adding %d/%d frames to DB", frameCount, n_frames ); + *(sql+strlen(sql)-2) = '\0'; + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert frames: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + last_db_frame = frames; + } + else + { + Debug( 1, "No valid pre-capture frames to add" ); + } +} + +void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image *alarm_image ) +{ + if ( !timestamp.tv_sec ) + { + Debug( 1, "Not adding new frame, zero timestamp" ); + return; + } + + frames++; + + static char event_file[PATH_MAX]; + snprintf( event_file, sizeof(event_file), capture_file_format, path, frames ); + + Debug( 1, "Writing capture frame %d", frames ); + WriteFrameImage( image, timestamp, event_file ); + + struct DeltaTimeval delta_time; + DELTA_TIMEVAL( delta_time, timestamp, start_time, DT_PREC_2 ); + + bool db_frame = (score>=0) || ((frames%config.bulk_frame_interval)==0) || !frames; + + if ( db_frame ) + { + const char *frame_type = score>0?"Alarm":(score<0?"Bulk":"Normal"); + + Debug( 1, "Adding frame %d to DB", frames ); + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Frames ( EventId, FrameId, Type, TimeStamp, Delta, Score ) values ( %d, %d, '%s', from_unixtime( %ld ), %s%ld.%02ld, %d )", id, frames, frame_type, timestamp.tv_sec, delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, score ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert frame: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + last_db_frame = frames; + + // We are writing a bulk frame + if ( score < 0 ) + { + snprintf( sql, sizeof(sql), "update Events set Length = %s%ld.%02ld, Frames = %d, AlarmFrames = %d, TotScore = %d, AvgScore = %d, MaxScore = %d where Id = %d", delta_time.positive?"":"-", delta_time.sec, delta_time.fsec, frames, alarm_frames, tot_score, (int)(alarm_frames?(tot_score/alarm_frames):0), max_score, id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't update event: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + } + } + + end_time = timestamp; + + if ( score > 0 ) + { + alarm_frames++; + + tot_score += score; + if ( score > (int)max_score ) + max_score = score; + + if ( alarm_image ) + { + snprintf( event_file, sizeof(event_file), analyse_file_format, path, frames ); + + Debug( 1, "Writing analysis frame %d", frames ); + WriteFrameImage( alarm_image, timestamp, event_file, true ); + } + } + + /* This makes viewing the diagnostic images impossible because it keeps deleting them + if ( config.record_diag_images ) + { + char diag_glob[PATH_MAX] = ""; + + snprintf( diag_glob, sizeof(diag_glob), "%s/%d/diag-*.jpg", config.dir_events, monitor->Id() ); + glob_t pglob; + int glob_status = glob( diag_glob, 0, 0, &pglob ); + if ( glob_status != 0 ) + { + if ( glob_status < 0 ) + { + Error( "Can't glob '%s': %s", diag_glob, strerror(errno) ); + } + else + { + Debug( 1, "Can't glob '%s': %d", diag_glob, glob_status ); + } + } + else + { + char new_diag_path[PATH_MAX] = ""; + for ( int i = 0; i < pglob.gl_pathc; i++ ) + { + char *diag_path = pglob.gl_pathv[i]; + + char *diag_file = strstr( diag_path, "diag-" ); + + if ( diag_file ) + { + snprintf( new_diag_path, sizeof(new_diag_path), general_file_format, path, frames, diag_file ); + + if ( rename( diag_path, new_diag_path ) < 0 ) + { + Error( "Can't rename '%s' to '%s': %s", diag_path, new_diag_path, strerror(errno) ); + } + } + } + } + globfree( &pglob ); + } + */ +} + +bool EventStream::loadInitialEventData( int monitor_id, time_t event_time ) +{ + static char sql[ZM_SQL_SML_BUFSIZ]; + + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %d and unix_timestamp( EndTime ) > %ld order by Id asc limit 1", monitor_id, event_time ); + + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + MYSQL_ROW dbrow = mysql_fetch_row( result ); + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + int init_event_id = atoi( dbrow[0] ); + + mysql_free_result( result ); + + loadEventData( init_event_id ); + + if ( event_time ) + { + curr_stream_time = event_time; + curr_frame_id = 1; + if ( event_time >= event_data->start_time ) + { + for (unsigned int i = 0; i < event_data->frame_count; i++ ) + { + //Info( "eft %d > et %d", event_data->frames[i].timestamp, event_time ); + if ( event_data->frames[i].timestamp >= event_time ) + { + curr_frame_id = i+1; + Debug( 3, "Set cst:%.2f", curr_stream_time ); + Debug( 3, "Set cfid:%d", curr_frame_id ); + break; + } + } + Debug( 3, "Skipping %ld frames", event_data->frame_count ); + } + } + return( true ); +} + +bool EventStream::loadInitialEventData( int init_event_id, int init_frame_id ) +{ + loadEventData( init_event_id ); + + if ( init_frame_id ) + { + curr_stream_time = event_data->frames[init_frame_id-1].timestamp; + curr_frame_id = init_frame_id; + } + else + { + curr_stream_time = event_data->start_time; + } + + return( true ); +} + +bool EventStream::loadEventData( int event_id ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + + snprintf( sql, sizeof(sql), "select M.Id, M.Name, E.Frames, unix_timestamp( StartTime ) as StartTimestamp, max(F.Delta)-min(F.Delta) as Duration from Events as E inner join Monitors as M on E.MonitorId = M.Id inner join Frames as F on E.Id = F.EventId where E.Id = %d group by E.Id", event_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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + if ( !mysql_num_rows( result ) ) + { + Fatal( "Unable to load event %d, not found in DB", event_id ); + } + + MYSQL_ROW dbrow = mysql_fetch_row( result ); + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + delete event_data; + event_data = new EventData; + event_data->event_id = event_id; + event_data->monitor_id = atoi( dbrow[0] ); + event_data->start_time = atoi(dbrow[3]); + if ( config.use_deep_storage ) + { + struct tm *event_time = localtime( &event_data->start_time ); + if ( config.dir_events[0] == '/' ) + snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); + else + snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%02d/%02d/%02d/%02d/%02d/%02d", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_time->tm_year-100, event_time->tm_mon+1, event_time->tm_mday, event_time->tm_hour, event_time->tm_min, event_time->tm_sec ); + } + else + { + if ( config.dir_events[0] == '/' ) + snprintf( event_data->path, sizeof(event_data->path), "%s/%ld/%ld", config.dir_events, event_data->monitor_id, event_data->event_id ); + else + snprintf( event_data->path, sizeof(event_data->path), "%s/%s/%ld/%ld", staticConfig.PATH_WEB.c_str(), config.dir_events, event_data->monitor_id, event_data->event_id ); + } + event_data->frame_count = atoi(dbrow[2]); + event_data->duration = atof(dbrow[4]); + + updateFrameRate( (double)event_data->frame_count/event_data->duration ); + + mysql_free_result( result ); + + snprintf( sql, sizeof(sql), "select FrameId, unix_timestamp( `TimeStamp` ), Delta from Frames where EventId = %d order by FrameId asc", event_id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + event_data->n_frames = mysql_num_rows( result ); + + event_data->frames = new FrameData[event_data->frame_count]; + int id, last_id = 0; + time_t timestamp, last_timestamp = event_data->start_time; + double delta, last_delta = 0.0; + while ( ( dbrow = mysql_fetch_row( result ) ) ) + { + id = atoi(dbrow[0]); + timestamp = atoi(dbrow[1]); + delta = atof(dbrow[2]); + int id_diff = id - last_id; + double frame_delta = (delta-last_delta)/id_diff; + if ( id_diff > 1 ) + { + for ( int i = last_id+1; i < id; i++ ) + { + event_data->frames[i-1].timestamp = (time_t)(last_timestamp + ((i-last_id)*frame_delta)); + event_data->frames[i-1].offset = (time_t)(event_data->frames[i-1].timestamp-event_data->start_time); + event_data->frames[i-1].delta = frame_delta; + event_data->frames[i-1].in_db = false; + } + } + event_data->frames[id-1].timestamp = timestamp; + event_data->frames[id-1].offset = (time_t)(event_data->frames[id-1].timestamp-event_data->start_time); + event_data->frames[id-1].delta = id>1?frame_delta:0.0; + event_data->frames[id-1].in_db = true; + last_id = id; + last_delta = delta; + last_timestamp = timestamp; + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + //for ( int i = 0; i < 250; i++ ) + //{ + //Info( "%d -> %d @ %f (%d)", i+1, event_data->frames[i].timestamp, event_data->frames[i].delta, event_data->frames[i].in_db ); + //} + + mysql_free_result( result ); + + if ( forceEventChange || mode == MODE_ALL_GAPLESS ) + { + if ( replay_rate > 0 ) + curr_stream_time = event_data->frames[0].timestamp; + else + curr_stream_time = event_data->frames[event_data->frame_count-1].timestamp; + } + Debug( 2, "Event:%ld, Frames:%ld, Duration: %.2f", event_data->event_id, event_data->frame_count, event_data->duration ); + + return( true ); +} + +void EventStream::processCommand( const CmdMsg *msg ) +{ + Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ) + // Check for incoming command + switch( (MsgCommand)msg->msg_data[0] ) + { + case CMD_PAUSE : + { + Debug( 1, "Got PAUSE command" ); + + // Set paused flag + paused = true; + replay_rate = ZM_RATE_BASE; + last_frame_sent = TV_2_FLOAT( now ); + break; + } + case CMD_PLAY : + { + Debug( 1, "Got PLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + replay_rate = ZM_RATE_BASE; + break; + } + case CMD_VARPLAY : + { + Debug( 1, "Got VARPLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; + break; + } + case CMD_STOP : + { + Debug( 1, "Got STOP command" ); + + // Clear paused flag + paused = false; + break; + } + case CMD_FASTFWD : + { + Debug( 1, "Got FAST FWD command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + // Set play rate + switch ( replay_rate ) + { + case 2 * ZM_RATE_BASE : + replay_rate = 5 * ZM_RATE_BASE; + break; + case 5 * ZM_RATE_BASE : + replay_rate = 10 * ZM_RATE_BASE; + break; + case 10 * ZM_RATE_BASE : + replay_rate = 25 * ZM_RATE_BASE; + break; + case 25 * ZM_RATE_BASE : + case 50 * ZM_RATE_BASE : + replay_rate = 50 * ZM_RATE_BASE; + break; + default : + replay_rate = 2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_SLOWFWD : + { + Debug( 1, "Got SLOW FWD command" ); + // Set paused flag + paused = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = 1; + break; + } + case CMD_SLOWREV : + { + Debug( 1, "Got SLOW REV command" ); + // Set paused flag + paused = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = -1; + break; + } + case CMD_FASTREV : + { + Debug( 1, "Got FAST REV command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + } + // Set play rate + switch ( replay_rate ) + { + case -2 * ZM_RATE_BASE : + replay_rate = -5 * ZM_RATE_BASE; + break; + case -5 * ZM_RATE_BASE : + replay_rate = -10 * ZM_RATE_BASE; + break; + case -10 * ZM_RATE_BASE : + replay_rate = -25 * ZM_RATE_BASE; + break; + case -25 * ZM_RATE_BASE : + case -50 * ZM_RATE_BASE : + replay_rate = -50 * ZM_RATE_BASE; + break; + default : + replay_rate = -2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_ZOOMIN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); + switch ( zoom ) + { + case 100: + zoom = 150; + break; + case 150: + zoom = 200; + break; + case 200: + zoom = 300; + break; + case 300: + zoom = 400; + break; + case 400: + default : + zoom = 500; + break; + } + break; + } + case CMD_ZOOMOUT : + { + Debug( 1, "Got ZOOM OUT command" ); + switch ( zoom ) + { + case 500: + zoom = 400; + break; + case 400: + zoom = 300; + break; + case 300: + zoom = 200; + break; + case 200: + zoom = 150; + break; + case 150: + default : + zoom = 100; + break; + } + break; + } + case CMD_PAN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got PAN command, to %d,%d", x, y ); + break; + } + case CMD_SCALE : + { + scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + Debug( 1, "Got SCALE command, to %d", scale ); + break; + } + case CMD_PREV : + { + Debug( 1, "Got PREV command" ); + if ( replay_rate >= 0 ) + curr_frame_id = 0; + else + curr_frame_id = event_data->frame_count-1; + paused = false; + forceEventChange = true; + break; + } + case CMD_NEXT : + { + Debug( 1, "Got NEXT command" ); + if ( replay_rate >= 0 ) + curr_frame_id = event_data->frame_count-1; + else + curr_frame_id = 0; + paused = false; + forceEventChange = true; + break; + } + case CMD_SEEK : + { + int offset = ((unsigned char)msg->msg_data[1]<<24)|((unsigned char)msg->msg_data[2]<<16)|((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + curr_frame_id = (int)(event_data->frame_count*offset/event_data->duration); + Debug( 1, "Got SEEK command, to %d (new cfid: %d)", offset, curr_frame_id ); + break; + } + case CMD_QUERY : + { + Debug( 1, "Got QUERY command, sending STATUS" ); + break; + } + default : + { + // Do nothing, for now + } + } + struct { + int event; + int progress; + int rate; + int zoom; + bool paused; + } status_data; + + status_data.event = event_data->event_id; + status_data.progress = (int)event_data->frames[curr_frame_id-1].offset; + status_data.rate = replay_rate; + status_data.zoom = zoom; + status_data.paused = paused; + Debug( 2, "E:%d, P:%d, p:%d R:%d, Z:%d", + status_data.event, + status_data.paused, + status_data.progress, + status_data.rate, + status_data.zoom + ); + + DataMsg status_msg; + status_msg.msg_type = MSG_DATA_EVENT; + memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) ); + if ( sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) ) < 0 ) + { + //if ( errno != EAGAIN ) + { + Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + exit( -1 ); + } + } + + updateFrameRate( (double)event_data->frame_count/event_data->duration ); +} + +void EventStream::checkEventLoaded() +{ + bool reload_event = false; + static char sql[ZM_SQL_SML_BUFSIZ]; + + if ( curr_frame_id <= 0 ) + { + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id < %ld order by Id desc limit 1", event_data->monitor_id, event_data->event_id ); + reload_event = true; + } + else if ( (unsigned int)curr_frame_id > event_data->frame_count ) + { + snprintf( sql, sizeof(sql), "select Id from Events where MonitorId = %ld and Id > %ld order by Id asc limit 1", event_data->monitor_id, event_data->event_id ); + reload_event = true; + } + + if ( reload_event ) + { + if ( forceEventChange || mode != MODE_SINGLE ) + { + //Info( "SQL:%s", sql ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + MYSQL_ROW dbrow = mysql_fetch_row( result ); + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + if ( dbrow ) + { + int event_id = atoi(dbrow[0]); + Debug( 1, "Loading new event %d", event_id ); + + loadEventData( event_id ); + + Debug( 2, "Current frame id = %d", curr_frame_id ); + if ( curr_frame_id <= 0 ) + curr_frame_id = event_data->frame_count; + else + curr_frame_id = 1; + Debug( 2, "New frame id = %d", curr_frame_id ); + } + else + { + if ( curr_frame_id <= 0 ) + curr_frame_id = 1; + else + curr_frame_id = event_data->frame_count; + paused = true; + } + mysql_free_result( result ); + forceEventChange = false; + } + else + { + if ( curr_frame_id <= 0 ) + curr_frame_id = 1; + else + curr_frame_id = event_data->frame_count; + paused = true; + } + } +} + +bool EventStream::sendFrame( int delta_us ) +{ + Debug( 2, "Sending frame %d", curr_frame_id ); + + static char filepath[PATH_MAX]; + static struct stat filestat; + FILE *fdj = NULL; + + snprintf( filepath, sizeof(filepath), Event::capture_file_format, event_data->path, curr_frame_id ); + +#if HAVE_LIBAVCODEC + if ( type == STREAM_MPEG ) + { + Image image( filepath ); + + Image *send_image = prepareImage( &image ); + + if ( !vid_stream ) + { + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); + } + /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_us*1000 ); + } + else +#endif // HAVE_LIBAVCODEC + { + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + + int img_buffer_size = 0; + uint8_t *img_buffer = temp_img_buffer; + + bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + + if ( type != STREAM_JPEG ) + send_raw = false; + + if ( send_raw ) + { + fdj = fopen( filepath, "rb" ); + if ( !fdj ) + { + Error( "Can't open %s: %s", filepath, strerror(errno) ); + return( false ); + } +#if HAVE_SENDFILE + if( fstat(fileno(fdj),&filestat) < 0 ) { + Error( "Failed getting information about file %s: %s", filepath, strerror(errno) ); + return( false ); + } +#else + img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); +#endif + } + else + { + Image image( filepath ); + + Image *send_image = prepareImage( &image ); + + switch( type ) + { + case STREAM_JPEG : + send_image->EncodeJpeg( img_buffer, &img_buffer_size ); + break; + case STREAM_RAW : + img_buffer = (uint8_t*)(send_image->Buffer()); + img_buffer_size = send_image->Size(); + break; + case STREAM_ZIP : + unsigned long zip_buffer_size; + send_image->Zip( img_buffer, &zip_buffer_size ); + img_buffer_size = zip_buffer_size; + break; + default: + Fatal( "Unexpected frame type %d", type ); + break; + } + } + + switch( type ) + { + case STREAM_JPEG : + fprintf( stdout, "Content-Type: image/jpeg\r\n" ); + break; + case STREAM_RAW : + fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); + break; + case STREAM_ZIP : + fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); + break; + default : + Fatal( "Unexpected frame type %d", type ); + break; + } + + + if(send_raw) { +#if HAVE_SENDFILE + fprintf( stdout, "Content-Length: %d\r\n\r\n", (int)filestat.st_size ); + if(sendfile(fileno(stdout), fileno(fdj), 0, (int)filestat.st_size) != (int)filestat.st_size) { + /* sendfile() failed, use standard way instead */ + img_buffer_size = fread( img_buffer, 1, sizeof(temp_img_buffer), fdj ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { + Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); + return( false ); + } + } +#else + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) { + Error("Unable to send raw frame %u: %s",curr_frame_id,strerror(errno)); + return( false ); + } +#endif + fclose(fdj); /* Close the file handle */ + } else { + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + } + + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); +} + +void EventStream::runStream() +{ + Event::Initialise(); + + openComms(); + + checkInitialised(); + + updateFrameRate( (double)event_data->frame_count/event_data->duration ); + + if ( type == STREAM_JPEG ) + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + + if ( !event_data ) + { + sendTextFrame( "No event data found" ); + exit( 0 ); + } + + unsigned int delta_us = 0; + while( !zm_terminate ) + { + gettimeofday( &now, NULL ); + + while(checkCommandQueue()); + + if ( step != 0 ) + curr_frame_id += step; + + checkEventLoaded(); + + // Get current frame data + FrameData *frame_data = &event_data->frames[curr_frame_id-1]; + + //Info( "cst:%.2f", curr_stream_time ); + //Info( "cfid:%d", curr_frame_id ); + //Info( "fdt:%d", frame_data->timestamp ); + if ( !paused ) + { + bool in_event = true; + double time_to_event = 0; + if ( replay_rate > 0 ) + { + time_to_event = event_data->frames[0].timestamp - curr_stream_time; + if ( time_to_event > 0 ) + in_event = false; + } + else if ( replay_rate < 0 ) + { + time_to_event = curr_stream_time - event_data->frames[event_data->frame_count-1].timestamp; + if ( time_to_event > 0 ) + in_event = false; + } + if ( !in_event ) + { + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( actual_delta_time > 1 ) + { + static char frame_text[64]; + snprintf( frame_text, sizeof(frame_text), "Time to next event = %d seconds", (int)time_to_event ); + if ( !sendTextFrame( frame_text ) ) + zm_terminate = true; + } + //else + //{ + usleep( STREAM_PAUSE_WAIT ); + //curr_stream_time += (replay_rate>0?1:-1) * ((1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000)); + curr_stream_time += (1.0L * replay_rate * STREAM_PAUSE_WAIT)/(ZM_RATE_BASE * 1000000); + //} + continue; + } + } + + // Figure out if we should send this frame + bool send_frame = false; + if ( !paused ) + { + // If we are streaming and this frame is due to be sent + if ( ((curr_frame_id-1)%frame_mod) == 0 ) + { + delta_us = (unsigned int)(frame_data->delta * 1000000); + if ( effective_fps < base_fps ) + delta_us = (unsigned int)((delta_us * base_fps)/effective_fps); + send_frame = true; + } + } + else if ( step != 0 ) + { + // We are paused and are just stepping forward or backward one frame + step = 0; + send_frame = true; + } + else + { + // We are paused, and doing nothing + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( actual_delta_time > MAX_STREAM_DELAY ) + { + // Send keepalive + Debug( 2, "Sending keepalive frame" ); + send_frame = true; + } + } + + if ( send_frame ) + if ( !sendFrame( delta_us ) ) + zm_terminate = true; + + curr_stream_time = frame_data->timestamp; + + if ( !paused ) + { + curr_frame_id += replay_rate>0?1:-1; + if ( send_frame && type != STREAM_MPEG ) + { + Debug( 3, "dUs: %d", delta_us ); + usleep( delta_us ); + } + } + else + { + usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); + } + } +#if HAVE_LIBAVCODEC + if ( type == STREAM_MPEG ) + delete vid_stream; +#endif // HAVE_LIBAVCODEC + + closeComms(); +} diff --git a/src/zm_event.h b/src/zm_event.h new file mode 100644 index 000000000..7029a9f5c --- /dev/null +++ b/src/zm_event.h @@ -0,0 +1,266 @@ +// +// ZoneMinder Core Interfaces, $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. +// + +#ifndef ZM_EVENT_H +#define ZM_EVENT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "zm.h" +#include "zm_image.h" +#include "zm_stream.h" + +class Zone; +class Monitor; + +#define MAX_PRE_ALARM_FRAMES 16 // Maximum number of prealarm frames that can be stored + +// +// Class describing events, i.e. captured periods of activity. +// +class Event +{ +friend class EventStream; + +protected: + static bool initialised; + static char capture_file_format[PATH_MAX]; + static char analyse_file_format[PATH_MAX]; + static char general_file_format[PATH_MAX]; + +protected: + static int sd; + +public: + typedef std::set StringSet; + typedef std::map StringSetMap; + +protected: + typedef enum { NORMAL, BULK, ALARM } FrameType; + + struct PreAlarmData + { + Image *image; + struct timeval timestamp; + unsigned int score; + Image *alarm_frame; + }; + + static int pre_alarm_count; + static PreAlarmData pre_alarm_data[MAX_PRE_ALARM_FRAMES]; + +protected: + unsigned int id; + Monitor *monitor; + struct timeval start_time; + struct timeval end_time; + std::string cause; + StringSetMap noteSetMap; + int frames; + int alarm_frames; + unsigned int tot_score; + unsigned int max_score; + char path[PATH_MAX]; + +protected: + int last_db_frame; + +protected: + static void Initialise() + { + if ( initialised ) + return; + + snprintf( capture_file_format, sizeof(capture_file_format), "%%s/%%0%dd-capture.jpg", config.event_image_digits ); + snprintf( analyse_file_format, sizeof(analyse_file_format), "%%s/%%0%dd-analyse.jpg", config.event_image_digits ); + snprintf( general_file_format, sizeof(general_file_format), "%%s/%%0%dd-%%s", config.event_image_digits ); + + initialised = true; + } + + void createNotes( std::string ¬es ); + +public: + static bool OpenFrameSocket( int ); + static bool ValidateFrameSocket( int ); + +public: + Event( Monitor *p_monitor, struct timeval p_start_time, const std::string &p_cause, const StringSetMap &p_noteSetMap ); + ~Event(); + + int Id() const { return( id ); } + const std::string &Cause() { return( cause ); } + int Frames() const { return( frames ); } + int AlarmFrames() const { return( alarm_frames ); } + + const struct timeval &StartTime() const { return( start_time ); } + const struct timeval &EndTime() const { return( end_time ); } + struct timeval &EndTime() { return( end_time ); } + + bool SendFrameImage( const Image *image, bool alarm_frame=false ); + bool WriteFrameImage( Image *image, struct timeval timestamp, const char *event_file, bool alarm_frame=false ); + + void updateNotes( const StringSetMap &stringSetMap ); + + void AddFrames( int n_frames, Image **images, struct timeval **timestamps ); + void AddFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ); + +public: + static const char *getSubPath( struct tm *time ) + { + static char subpath[PATH_MAX] = ""; + snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); + return( subpath ); + } + static const char *getSubPath( time_t *time ) + { + return( Event::getSubPath( localtime( time ) ) ); + } + +public: + static int PreAlarmCount() + { + return( pre_alarm_count ); + } + static void EmptyPreAlarmFrames() + { + if ( pre_alarm_count > 0 ) + { + for ( int i = 0; i < MAX_PRE_ALARM_FRAMES; i++ ) + { + delete pre_alarm_data[i].image; + delete pre_alarm_data[i].alarm_frame; + } + memset( pre_alarm_data, 0, sizeof(pre_alarm_data) ); + } + pre_alarm_count = 0; + } + static void AddPreAlarmFrame( Image *image, struct timeval timestamp, int score=0, Image *alarm_frame=NULL ) + { + pre_alarm_data[pre_alarm_count].image = new Image( *image ); + pre_alarm_data[pre_alarm_count].timestamp = timestamp; + pre_alarm_data[pre_alarm_count].score = score; + if ( alarm_frame ) + { + pre_alarm_data[pre_alarm_count].alarm_frame = new Image( *alarm_frame ); + } + pre_alarm_count++; + } + void SavePreAlarmFrames() + { + for ( int i = 0; i < pre_alarm_count; i++ ) + { + AddFrame( pre_alarm_data[i].image, pre_alarm_data[i].timestamp, pre_alarm_data[i].score, pre_alarm_data[i].alarm_frame ); + } + EmptyPreAlarmFrames(); + } +}; + +class EventStream : public StreamBase +{ +public: + typedef enum { MODE_SINGLE, MODE_ALL, MODE_ALL_GAPLESS } StreamMode; + +protected: + struct FrameData { + //unsigned long id; + time_t timestamp; + time_t offset; + double delta; + bool in_db; + }; + + struct EventData + { + unsigned long event_id; + unsigned long monitor_id; + unsigned long frame_count; + time_t start_time; + double duration; + char path[PATH_MAX]; + int n_frames; + FrameData *frames; + }; + +protected: + static const int STREAM_PAUSE_WAIT = 250000; // Microseconds + + static const StreamMode DEFAULT_MODE = MODE_SINGLE; + +protected: + StreamMode mode; + bool forceEventChange; + +protected: + int curr_frame_id; + double curr_stream_time; + + EventData *event_data; + +protected: + bool loadEventData( int event_id ); + bool loadInitialEventData( int init_event_id, int init_frame_id ); + bool loadInitialEventData( int monitor_id, time_t event_time ); + + void checkEventLoaded(); + void processCommand( const CmdMsg *msg ); + bool sendFrame( int delta_us ); + +public: + EventStream() + { + mode = DEFAULT_MODE; + + forceEventChange = false; + + curr_frame_id = 0; + curr_stream_time = 0.0; + + event_data = 0; + } + void setStreamStart( int init_event_id, int init_frame_id=0 ) + { + loadInitialEventData( init_event_id, init_frame_id ); + loadMonitor( event_data->monitor_id ); + } + void setStreamStart( int monitor_id, time_t event_time ) + { + loadInitialEventData( monitor_id, event_time ); + loadMonitor( monitor_id ); + } + void setStreamMode( StreamMode p_mode ) + { + mode = p_mode; + } + void runStream(); +}; + +#endif // ZM_EVENT_H diff --git a/src/zm_exception.cpp b/src/zm_exception.cpp new file mode 100644 index 000000000..b7fe9e9a4 --- /dev/null +++ b/src/zm_exception.cpp @@ -0,0 +1,22 @@ +// +// ZoneMinder Exception Class Implementation, $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. +// + +#include "zm_exception.h" + +// Blank diff --git a/src/zm_exception.h b/src/zm_exception.h new file mode 100644 index 000000000..4af60bfa6 --- /dev/null +++ b/src/zm_exception.h @@ -0,0 +1,68 @@ +// +// ZoneMinder Exception Class Interface, $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. +// + +#ifndef ZM_EXCEPTION_H +#define ZM_EXCEPTION_H + +#include "zm.h" + +#include + +class Exception +{ +protected: + typedef enum { INFO, WARNING, ERROR, FATAL } Severity; + +protected: + std::string mMessage; + Severity mSeverity; + +public: + Exception( const std::string &message, Severity severity=ERROR ) : mMessage( message ), mSeverity( severity ) + { + } + +public: + const std::string &getMessage() const + { + return( mMessage ); + } + Severity getSeverity() const + { + return( mSeverity ); + } + bool isInfo() const + { + return( mSeverity == INFO ); + } + bool isWarning() const + { + return( mSeverity == WARNING ); + } + bool isError() const + { + return( mSeverity == ERROR ); + } + bool isFatal() const + { + return( mSeverity == FATAL ); + } +}; + +#endif // ZM_EXCEPTION_H diff --git a/src/zm_ffmpeg.cpp b/src/zm_ffmpeg.cpp new file mode 100644 index 000000000..577a188ca --- /dev/null +++ b/src/zm_ffmpeg.cpp @@ -0,0 +1,24 @@ +/* + * ZoneMinder FFMPEG implementation, $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. +*/ + +#if HAVE_LIBAVCODEC + +#include "zm_ffmpeg.h" + +#endif // HAVE_LIBAVCODEC diff --git a/src/zm_ffmpeg.h b/src/zm_ffmpeg.h new file mode 100644 index 000000000..059f88b39 --- /dev/null +++ b/src/zm_ffmpeg.h @@ -0,0 +1,74 @@ +/* + * ZoneMinder FFMPEG Interface, $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. +*/ + +#ifndef ZM_FFMPEG_H +#define ZM_FFMPEG_H + +#if HAVE_LIBAVCODEC + +#ifdef __cplusplus +extern "C" { +#endif +#if HAVE_LIBAVUTIL_AVUTIL_H +#include +#endif +#if HAVE_LIBAVCODEC_AVCODEC_H +#include +#endif +#if HAVE_LIBAVFORMAT_AVFORMAT_H +#include +#endif +#if HAVE_LIBSWSCALE +#if HAVE_LIBSWSCALE_SWSCALE_H +#include +#include // this is a fix for error: ‘av_rescale_q’ was not declared in this scope +#endif +#endif // HAVE_LIBSWSCALE +#ifdef __cplusplus +} +#endif + +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + #if defined(AVIO_WRONLY) + #define AVIO_FLAG_WRITE AVIO_WRONLY + #else + #define AVIO_FLAG_WRITE URL_WRONLY + #endif +#endif + +#if FFMPEG_VERSION_INT == 0x000408 +#define ZM_FFMPEG_048 1 +#elif FFMPEG_VERSION_INT == 0x000409 +#if LIBAVCODEC_VERSION_INT < ((50<<16)+(0<<8)+0) +#define ZM_FFMPEG_049 1 +#else // LIBAVCODEC_VERSION_INT +#define ZM_FFMPEG_SVN 1 +#endif // LIBAVCODEC_VERSION_INT +#else // FFMPEG_VERSION_INT +#define ZM_FFMPEG_SVN 1 +#endif // FFMPEG_VERSION_INT + +/* Fix for not having SWS_CPU_CAPS_SSE2 defined */ +#ifndef SWS_CPU_CAPS_SSE2 +#define SWS_CPU_CAPS_SSE2 0x02000000 +#endif + +#endif // HAVE_LIBAVCODEC + +#endif // ZM_FFMPEG_H diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp new file mode 100644 index 000000000..c69907d9c --- /dev/null +++ b/src/zm_ffmpeg_camera.cpp @@ -0,0 +1,263 @@ +// +// ZoneMinder Ffmpeg Camera Class Implementation, $Date: 2009-01-16 12:18:50 +0000 (Fri, 16 Jan 2009) $, $Revision: 2713 $ +// 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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_ffmpeg_camera.h" + +FfmpegCamera::FfmpegCamera( int p_id, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + Camera( p_id, FFMPEG_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + mPath( p_path ) +{ + if ( capture ) + { + Initialise(); + } + + mFormatContext = NULL; + mVideoStreamId = -1; + mCodecContext = NULL; + mCodec = NULL; + mRawFrame = NULL; + mFrame = NULL; + frameCount = 0; + +#if HAVE_LIBSWSCALE + mConvertContext = NULL; +#endif + /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + +} + +FfmpegCamera::~FfmpegCamera() +{ + av_freep( &mFrame ); + av_freep( &mRawFrame ); + +#if HAVE_LIBSWSCALE + if ( mConvertContext ) + { + sws_freeContext( mConvertContext ); + mConvertContext = NULL; + } +#endif + + if ( mCodecContext ) + { + avcodec_close( mCodecContext ); + mCodecContext = NULL; // Freed by av_close_input_file + } + if ( mFormatContext ) + { +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + av_close_input_file( mFormatContext ); +#else + avformat_close_input( &mFormatContext ); +#endif + mFormatContext = NULL; + } + + if ( capture ) + { + Terminate(); + } +} + +void FfmpegCamera::Initialise() +{ + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); + + av_register_all(); +} + +void FfmpegCamera::Terminate() +{ +} + +int FfmpegCamera::PrimeCapture() +{ + Info( "Priming capture from %s", mPath.c_str() ); + + // Open the input, not necessarily a file +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + if ( av_open_input_file( &mFormatContext, mPath.c_str(), NULL, 0, NULL ) !=0 ) +#else + if ( avformat_open_input( &mFormatContext, mPath.c_str(), NULL, NULL ) !=0 ) +#endif + Fatal( "Unable to open input %s due to: %s", mPath.c_str(), strerror(errno) ); + + // Locate stream info from input +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + if ( av_find_stream_info( mFormatContext ) < 0 ) +#else + if ( avformat_find_stream_info( mFormatContext, 0 ) < 0 ) +#endif + Fatal( "Unable to find stream info from %s due to: %s", mPath.c_str(), strerror(errno) ); + + // Find first video stream present + mVideoStreamId = -1; + for (unsigned int i=0; i < mFormatContext->nb_streams; i++ ) + { +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) +#else + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) +#endif + { + mVideoStreamId = i; + break; + } + } + if ( mVideoStreamId == -1 ) + Fatal( "Unable to locate video stream in %s", mPath.c_str() ); + + mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; + + // Try and get the codec from the codec context + if ( (mCodec = avcodec_find_decoder( mCodecContext->codec_id )) == NULL ) + Fatal( "Can't find codec for video stream from %s", mPath.c_str() ); + + // Open the codec +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0) + if ( avcodec_open( mCodecContext, mCodec ) < 0 ) +#else + if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) +#endif + Fatal( "Unable to open codec for video stream from %s", mPath.c_str() ); + + // Allocate space for the native video frame + mRawFrame = avcodec_alloc_frame(); + + // Allocate space for the converted video frame + mFrame = avcodec_alloc_frame(); + + if(mRawFrame == NULL || mFrame == NULL) + Fatal( "Unable to allocate frame for %s", mPath.c_str() ); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } + +#if HAVE_LIBSWSCALE + if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { + Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); + } + + if(!sws_isSupportedOutput(imagePixFormat)) { + Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + } + +#else // HAVE_LIBSWSCALE + Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); +#endif // HAVE_LIBSWSCALE + + return( 0 ); +} + +int FfmpegCamera::PreCapture() +{ + // Nothing to do here + return( 0 ); +} + +int FfmpegCamera::Capture( Image &image ) +{ + AVPacket packet; + uint8_t* directbuffer; + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } + + int frameComplete = false; + while ( !frameComplete ) + { + int avResult = av_read_frame( mFormatContext, &packet ); + if ( avResult < 0 ) + { + Error( "Unable to read packet from stream %d: error %d", packet.stream_index, avResult ); + return( -1 ); + } + Debug( 5, "Got packet from stream %d", packet.stream_index ); + if ( packet.stream_index == mVideoStreamId ) + { + if ( avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ) < 0 ) + Fatal( "Unable to decode frame at frame %d", frameCount ); + + Debug( 4, "Decoded video packet at frame %d", frameCount ); + + if ( frameComplete ) + { + Debug( 3, "Got frame %d", frameCount ); + + avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); + +#if HAVE_LIBSWSCALE + if(mConvertContext == NULL) { + if(config.cpu_extensions && sseversion >= 20) { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL ); + } else { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + } + if(mConvertContext == NULL) + Fatal( "Unable to create conversion context for %s", mPath.c_str() ); + } + + if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) + Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); +#else // HAVE_LIBSWSCALE + Fatal( "You must compile ffmpeg with the --enable-swscale option to use ffmpeg cameras" ); +#endif // HAVE_LIBSWSCALE + + frameCount++; + } + } + av_free_packet( &packet ); + } + return (0); +} + +int FfmpegCamera::PostCapture() +{ + // Nothing to do here + return( 0 ); +} + +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_ffmpeg_camera.h b/src/zm_ffmpeg_camera.h new file mode 100644 index 000000000..3b256d5d6 --- /dev/null +++ b/src/zm_ffmpeg_camera.h @@ -0,0 +1,69 @@ +// +// ZoneMinder Ffmpeg Class Interface, $Date: 2008-07-25 10:33:23 +0100 (Fri, 25 Jul 2008) $, $Revision: 2611 $ +// 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. +// + +#ifndef ZM_FFMPEG_CAMERA_H +#define ZM_FFMPEG_CAMERA_H + +#include "zm_camera.h" + +#include "zm_buffer.h" +//#include "zm_utils.h" +#include "zm_ffmpeg.h" + +// +// Class representing 'remote' cameras, i.e. those which are +// accessed over a network connection. +// +class FfmpegCamera : public Camera +{ +protected: + std::string mPath; + + int frameCount; + +#if HAVE_LIBAVFORMAT + AVFormatContext *mFormatContext; + int mVideoStreamId; + AVCodecContext *mCodecContext; + AVCodec *mCodec; + AVFrame *mRawFrame; + AVFrame *mFrame; + PixelFormat imagePixFormat; +#endif // HAVE_LIBAVFORMAT + +#if HAVE_LIBSWSCALE + struct SwsContext *mConvertContext; +#endif + +public: + FfmpegCamera( int p_id, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~FfmpegCamera(); + + const std::string &Path() const { return( mPath ); } + + void Initialise(); + void Terminate(); + + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); +}; + +#endif // ZM_FFMPEG_CAMERA_H diff --git a/src/zm_file_camera.cpp b/src/zm_file_camera.cpp new file mode 100644 index 000000000..28ce2b155 --- /dev/null +++ b/src/zm_file_camera.cpp @@ -0,0 +1,91 @@ +// +// ZoneMinder File Camera Class Implementation, $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. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_file_camera.h" + +FileCamera::FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : Camera( p_id, FILE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ) +{ + strncpy( path, p_path, sizeof(path) ); + if ( capture ) + { + Initialise(); + } +} + +FileCamera::~FileCamera() +{ + if ( capture ) + { + Terminate(); + } +} + +void FileCamera::Initialise() +{ + if ( !path[0] ) + { + Error( "No path specified for file image" ); + exit( -1 ); + } +} + +void FileCamera::Terminate() +{ +} + +int FileCamera::PreCapture() +{ + struct stat statbuf; + if ( stat( path, &statbuf ) < 0 ) + { + Error( "Can't stat %s: %s", path, strerror(errno) ); + return( -1 ); + } + + while ( (time( 0 ) - statbuf.st_mtime) < 1 ) + { + usleep( 100000 ); + } + return( 0 ); +} + +int FileCamera::Capture( Image &image ) +{ + return( image.ReadJpeg( path, colours, subpixelorder )?0:-1 ); +} + +int FileCamera::PostCapture() +{ + return( 0 ); +} diff --git a/src/zm_file_camera.h b/src/zm_file_camera.h new file mode 100644 index 000000000..ad972e372 --- /dev/null +++ b/src/zm_file_camera.h @@ -0,0 +1,51 @@ +// +// ZoneMinder File Camera Class Interface, $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. +// + +#ifndef ZM_FILE_CAMERA_H +#define ZM_FILE_CAMERA_H + +#include "zm_camera.h" +#include "zm_buffer.h" +#include "zm_regexp.h" + +#include + +// +// Class representing 'file' cameras, i.e. those which are +// accessed over a network connection. +// +class FileCamera : public Camera +{ +protected: + char path[PATH_MAX]; + +public: + FileCamera( int p_id, const char *p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~FileCamera(); + + const char *Path() const { return( path ); } + + void Initialise(); + void Terminate(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); +}; + +#endif // ZM_FILE_CAMERA_H diff --git a/src/zm_font.h b/src/zm_font.h new file mode 100644 index 000000000..844ff4f1e --- /dev/null +++ b/src/zm_font.h @@ -0,0 +1,3337 @@ +/**********************************************/ +/* */ +/* Font file generated by rthelen */ +/* */ +/**********************************************/ + +static unsigned char fontdata[] = { + + /* 0 0x00 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^G' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^H' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 9 0x09 '^J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^K' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 11 0x0b '^L' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^M' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^O' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^P' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^Q' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^S' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^U' */ + 0x18, /* 000 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x78, /* 0 000 */ + 0x78, /* 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^V' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^W' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^X' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^Y' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Z' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^[' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^\' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^]' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^^' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^_' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^`' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x38, /* 00 000 */ + 0x14, /* 000 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x58, /* 0 0 000 */ + 0x28, /* 00 0 000 */ + 0x34, /* 00 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x18, /* 000 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x28, /* 00 0 000 */ + 0x48, /* 0 00 000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x74, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x60, /* 0 00000 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x02, /* 000000 0 */ + 0x02, /* 000000 0 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x70, /* 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '^?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '\200' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '\201' */ + 0x28, /* 00 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '\202' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '\203' */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '\204' */ + 0x58, /* 0 0 000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '\205' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '\206' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '\207' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 '\210' */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '\211' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '\212' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '\213' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '\214' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '\215' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '\216' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '\217' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '\220' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '\221' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '\222' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '\223' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '\224' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '\225' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '\226' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '\227' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '\230' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '\231' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '\232' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '\233' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '\234' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '\235' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '\236' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f '\237' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '\240' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '\241' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '\242' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '\243' */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x40, /* 0 000000 */ + 0x70, /* 0 0000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '\244' */ + 0x44, /* 0 000 00 */ + 0x24, /* 00 00 00 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x14, /* 000 0 00 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '\245' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '\246' */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x3c, /* 00 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '\247' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x58, /* 0 0 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '\250' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '\251' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x34, /* 00 0 00 */ + 0x44, /* 0 000 00 */ + 0x34, /* 00 0 00 */ + 0x08, /* 0000 000 */ + 0x70, /* 0 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '\252' */ + 0x00, /* 00000000 */ + 0x7a, /* 0 0 0 */ + 0x2e, /* 00 0 0 */ + 0x2e, /* 00 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '\253' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '\254' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '\255' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '\256' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x78, /* 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x5c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '\257' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '\260' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 177 0xb1 '\261' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 178 0xb2 '\262' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 179 0xb3 '\263' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 180 0xb4 '\264' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 181 0xb5 '\265' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x74, /* 0 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 182 0xb6 '\266' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x14, /* 000 0 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 183 0xb7 '\267' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x24, /* 00 00 00 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x24, /* 00 00 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 184 0xb8 '\270' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 185 0xb9 '\271' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 186 0xba '\272' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 187 0xbb '\273' */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 188 0xbc '\274' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '\275' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '\276' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '\277' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 192 0xc0 '\300' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '\301' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '\302' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 195 0xc3 '\303' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 196 0xc4 '\304' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '\305' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 198 0xc6 '\306' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 199 0xc7 '\307' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 200 0xc8 '\310' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '\311' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 202 0xca '\312' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '\313' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 204 0xcc '\314' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 205 0xcd '\315' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '\316' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x58, /* 0 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 207 0xcf '\317' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x2c, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '\320' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '\321' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 210 0xd2 '\322' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 211 0xd3 '\323' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '\324' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '\325' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 214 0xd6 '\326' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 215 0xd7 '\327' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 216 0xd8 '\330' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 217 0xd9 '\331' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '\332' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 219 0xdb '\333' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 220 0xdc '\334' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 221 0xdd '\335' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 222 0xde '\336' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 223 0xdf '\337' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '\340' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '\341' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '\342' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '\343' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '\344' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '\345' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '\346' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 '\347' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '\350' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 '\351' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '\352' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '\353' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec '\354' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '\355' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee '\356' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef '\357' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '\360' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '\361' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '\362' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '\363' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '\364' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 245 0xf5 '\365' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 '\366' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '\367' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '\370' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '\371' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '\372' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '\373' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc '\374' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '\375' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '\376' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '\377' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/src/zm_image.cpp b/src/zm_image.cpp new file mode 100644 index 000000000..829303f29 --- /dev/null +++ b/src/zm_image.cpp @@ -0,0 +1,5463 @@ +// +// ZoneMinder Image Class Implementation, $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. +// +#include "zm.h" +#include "zm_font.h" +#include "zm_image.h" +#include "zm_utils.h" +#include "zm_rgb.h" + +#include +#include + +bool Image::initialised = false; +static unsigned char *y_table; +static signed char *uv_table; +static short *r_v_table; +static short *g_v_table; +static short *g_u_table; +static short *b_u_table; +__attribute__((aligned(16))) static const uint8_t movemask[16] = {0,4,8,12,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + +jpeg_compress_struct *Image::jpg_ccinfo[101] = { 0 }; +jpeg_decompress_struct *Image::jpg_dcinfo = 0; +struct zm_error_mgr Image::jpg_err; + +/* Pointer to blend function. */ +static blend_fptr_t fptr_blend; + +/* Pointer to delta8 functions */ +static delta_fptr_t fptr_delta8_rgb; +static delta_fptr_t fptr_delta8_bgr; +static delta_fptr_t fptr_delta8_rgba; +static delta_fptr_t fptr_delta8_bgra; +static delta_fptr_t fptr_delta8_argb; +static delta_fptr_t fptr_delta8_abgr; +static delta_fptr_t fptr_delta8_gray8; + +/* Pointers to deinterlace_4field functions */ +static deinterlace_4field_fptr_t fptr_deinterlace_4field_rgba; +static deinterlace_4field_fptr_t fptr_deinterlace_4field_bgra; +static deinterlace_4field_fptr_t fptr_deinterlace_4field_argb; +static deinterlace_4field_fptr_t fptr_deinterlace_4field_abgr; +static deinterlace_4field_fptr_t fptr_deinterlace_4field_gray8; + +/* Pointer to image buffer memory copy function */ +imgbufcpy_fptr_t fptr_imgbufcpy; + +Image::Image() +{ + if ( !initialised ) + Initialise(); + width = 0; + height = 0; + pixels = 0; + colours = 0; + subpixelorder = 0; + size = 0; + allocation = 0; + buffer = 0; + buffertype = 0; + holdbuffer = 0; + text[0] = '\0'; +} + +Image::Image( const char *filename ) +{ + if ( !initialised ) + Initialise(); + width = 0; + height = 0; + pixels = 0; + colours = 0; + subpixelorder = 0; + size = 0; + allocation = 0; + buffer = 0; + buffertype = 0; + holdbuffer = 0; + ReadJpeg( filename, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB); + text[0] = '\0'; +} + +Image::Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer ) +{ + if ( !initialised ) + Initialise(); + width = p_width; + height = p_height; + pixels = width*height; + colours = p_colours; + subpixelorder = p_subpixelorder; + size = (width*height)*colours; + buffer = 0; + holdbuffer = 0; + if ( p_buffer ) + { + allocation = size; + buffertype = ZM_BUFTYPE_DONTFREE; + buffer = p_buffer; + } + else + { + AllocImgBuffer(size); + } + text[0] = '\0'; +} + +Image::Image( const Image &p_image ) +{ + if ( !initialised ) + Initialise(); + width = p_image.width; + height = p_image.height; + pixels = p_image.pixels; + colours = p_image.colours; + subpixelorder = p_image.subpixelorder; + size = allocation = p_image.size; + buffer = 0; + holdbuffer = 0; + AllocImgBuffer(allocation); + (*fptr_imgbufcpy)(buffer, p_image.buffer, size); + strncpy( text, p_image.text, sizeof(text) ); +} + +Image::~Image() +{ + DumpImgBuffer(); +} + +void Image::Initialise() +{ + /* Assign the blend pointer to function */ + if(config.fast_image_blends) { + if(config.cpu_extensions && sseversion >= 20) { + fptr_blend = &sse2_fastblend; /* SSE2 fast blend */ + Debug(2,"Blend: Using SSE2 fast blend function"); + } else { + fptr_blend = &std_fastblend; /* standard fast blend */ + Debug(2,"Blend: Using fast blend function"); + } + } else { + fptr_blend = &std_blend; + Debug(2,"Blend: Using standard blend function"); + } + + __attribute__((aligned(16))) uint8_t blend1[16] = {142,255,159,91,88,227,0,52,37,80,152,97,104,252,90,82}; + __attribute__((aligned(16))) uint8_t blend2[16] = {129,56,136,96,119,149,94,29,96,176,1,144,230,203,111,172}; + __attribute__((aligned(16))) uint8_t blendres[16]; + __attribute__((aligned(16))) uint8_t blendexp[16] = {141,231,157,92,91,217,11,49,45,92,133,103,119,246,92,93}; /* Expected results for 12.5% blend */ + + (*fptr_blend)(blend1,blend2,blendres,16,12.5); + + /* Compare results with expected results */ + for(int i=0;i<16;i++) { + if(abs(blendexp[i] - blendres[i]) > 3) { + Panic("Blend function failed self-test: Results differ from the expected results"); + } + } + + fptr_delta8_rgb = &std_delta8_rgb; + fptr_delta8_bgr = &std_delta8_bgr; + + /* Assign the delta functions */ + if(config.cpu_extensions) { + if(sseversion >= 35) { + /* SSSE3 available */ + fptr_delta8_rgba = &ssse3_delta8_rgba; + fptr_delta8_bgra = &ssse3_delta8_bgra; + fptr_delta8_argb = &ssse3_delta8_argb; + fptr_delta8_abgr = &ssse3_delta8_abgr; + fptr_delta8_gray8 = &sse2_delta8_gray8; + Debug(2,"Delta: Using SSSE3 delta functions"); + } else if(sseversion >= 20) { + /* SSE2 available */ + fptr_delta8_rgba = &sse2_delta8_rgba; + fptr_delta8_bgra = &sse2_delta8_bgra; + fptr_delta8_argb = &sse2_delta8_argb; + fptr_delta8_abgr = &sse2_delta8_abgr; + /* + ** On some systems, the 4 SSE2 algorithms above might be a little slower than + ** the standard algorithms, especially on early Pentium 4 processors. + ** In that case, comment out the 4 lines above and uncomment the 4 lines below + */ + // fptr_delta8_rgba = &std_delta8_rgba; + // fptr_delta8_bgra = &std_delta8_bgra; + // fptr_delta8_argb = &std_delta8_argb; + // fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &sse2_delta8_gray8; + Debug(2,"Delta: Using SSE2 delta functions"); + } else { + /* No suitable SSE version available */ + fptr_delta8_rgba = &std_delta8_rgba; + fptr_delta8_bgra = &std_delta8_bgra; + fptr_delta8_argb = &std_delta8_argb; + fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &std_delta8_gray8; + Debug(2,"Delta: Using standard delta functions"); + } + } else { + /* CPU extensions disabled */ + fptr_delta8_rgba = &std_delta8_rgba; + fptr_delta8_bgra = &std_delta8_bgra; + fptr_delta8_argb = &std_delta8_argb; + fptr_delta8_abgr = &std_delta8_abgr; + fptr_delta8_gray8 = &std_delta8_gray8; + Debug(2,"Delta: CPU extensions disabled, using standard delta functions"); + } + + /* Use SSSE3 deinterlace functions? */ + if(config.cpu_extensions && sseversion >= 35) { + fptr_deinterlace_4field_rgba = &ssse3_deinterlace_4field_rgba; + fptr_deinterlace_4field_bgra = &ssse3_deinterlace_4field_bgra; + fptr_deinterlace_4field_argb = &ssse3_deinterlace_4field_argb; + fptr_deinterlace_4field_abgr = &ssse3_deinterlace_4field_abgr; + fptr_deinterlace_4field_gray8 = &ssse3_deinterlace_4field_gray8; + Debug(2,"Deinterlace: Using SSSE3 delta functions"); + } else { + fptr_deinterlace_4field_rgba = &std_deinterlace_4field_rgba; + fptr_deinterlace_4field_bgra = &std_deinterlace_4field_bgra; + fptr_deinterlace_4field_argb = &std_deinterlace_4field_argb; + fptr_deinterlace_4field_abgr = &std_deinterlace_4field_abgr; + fptr_deinterlace_4field_gray8 = &std_deinterlace_4field_gray8; + Debug(2,"Deinterlace: Using standard delta functions"); + } + + /* Use SSE2 aligned memory copy? */ + if(config.cpu_extensions && sseversion >= 20) { + fptr_imgbufcpy = &sse2_aligned_memcpy; + Debug(2,"Image buffer copy: Using SSE2 aligned memcpy"); + } else { + fptr_imgbufcpy = &memcpy; + Debug(2,"Image buffer copy: Using standard memcpy"); + } + + /* Code below relocated from zm_local_camera */ + Debug( 3, "Setting up static colour tables" ); + + y_table = new unsigned char[256]; + for ( int i = 0; i <= 255; i++ ) + { + unsigned char c = i; + if ( c <= 16 ) + y_table[c] = 0; + else if ( c >= 235 ) + y_table[c] = 255; + else + y_table[c] = (255*(c-16))/219; + } + + uv_table = new signed char[256]; + for ( int i = 0; i <= 255; i++ ) + { + unsigned char c = i; + if ( c <= 16 ) + uv_table[c] = -127; + else if ( c >= 240 ) + uv_table[c] = 127; + else + uv_table[c] = (127*(c-128))/112; + } + + r_v_table = new short[255]; + g_v_table = new short[255]; + g_u_table = new short[255]; + b_u_table = new short[255]; + for ( int i = 0; i < 255; i++ ) + { + r_v_table[i] = (1402*(i-128))/1000; + g_u_table[i] = (344*(i-128))/1000; + g_v_table[i] = (714*(i-128))/1000; + b_u_table[i] = (1772*(i-128))/1000; + } + + initialised = true; +} + +/* Requests a writeable buffer to the image. This is safer than buffer() because this way we can gurantee that a buffer of required size exists */ +uint8_t* Image::WriteBuffer(const int p_width, const int p_height, const int p_colours, const int p_subpixelorder) { + unsigned int newsize; + + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("WriteBuffer called with unexpected colours: %d",p_colours); + return NULL; + } + + if(!p_height || !p_width) { + Error("WriteBuffer called with invaid width or height: %d %d",p_width,p_height); + return NULL; + } + + if(p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { + newsize = (p_width * p_height) * p_colours; + + if(buffer == NULL) { + AllocImgBuffer(newsize); + } else { + if(allocation < newsize) { + if(holdbuffer) { + Error("Held buffer is undersized for requested buffer"); + return NULL; + } else { + /* Replace buffer with a bigger one */ + DumpImgBuffer(); + AllocImgBuffer(newsize); + } + } + } + + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = newsize; + } + + return buffer; + +} + +/* Assign an existing buffer to the image instead of copying from a source buffer. The goal is to reduce the amount of memory copying and increase efficiency and buffer reusing. */ +void Image::AssignDirect( const int p_width, const int p_height, const int p_colours, const int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype) { + if(new_buffer == NULL) { + Error("Attempt to directly assign buffer from a NULL pointer"); + return; + } + + if(buffer_size < (unsigned int)((p_width*p_height)*p_colours)) { + Error("Attempt to directly assign buffer from an undersized buffer of size: %zu",buffer_size); + return; + } + + if(!p_height || !p_width) { + Error("Attempt to directly assign buffer with invalid width or height: %d %d",p_width,p_height); + return; + } + + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("Attempt to directly assign buffer with unexpected colours per pixel: %d",p_colours); + return; + } + + if(holdbuffer && buffer) { + if((unsigned int)((p_height*p_width)*p_colours) > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } else { + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = pixels*colours; + + /* Copy into the held buffer */ + if(new_buffer != buffer) + (*fptr_imgbufcpy)(buffer, new_buffer, size); + + /* Free the new buffer */ + DumpBuffer(new_buffer, p_buffertype); + } + } else { + /* Free an existing buffer if any */ + DumpImgBuffer(); + + width = p_width; + height = p_height; + colours = p_colours; + subpixelorder = p_subpixelorder; + pixels = height*width; + size = pixels*colours; + + allocation = buffer_size; + buffertype = p_buffertype; + buffer = new_buffer; + } + +} + +void Image::Assign(const int p_width, const int p_height, const int p_colours, const int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size) { + unsigned int new_size = (p_width * p_height) * p_colours; + + if(new_buffer == NULL) { + Error("Attempt to assign buffer from a NULL pointer"); + return; + } + + if(buffer_size < new_size) { + Error("Attempt to assign buffer from an undersized buffer of size: %zu",buffer_size); + return; + } + + if(!p_height || !p_width) { + Error("Attempt to assign buffer with invalid width or height: %d %d",p_width,p_height); + return; + } + + if(p_colours != ZM_COLOUR_GRAY8 && p_colours != ZM_COLOUR_RGB24 && p_colours != ZM_COLOUR_RGB32) { + Error("Attempt to assign buffer with unexpected colours per pixel: %d",p_colours); + return; + } + + if ( !buffer || p_width != width || p_height != height || p_colours != colours || p_subpixelorder != subpixelorder) { + + if (holdbuffer && buffer) { + if (new_size > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } + } else { + if(new_size > allocation || !buffer) { + DumpImgBuffer(); + AllocImgBuffer(new_size); + } + } + + width = p_width; + height = p_height; + pixels = width*height; + colours = p_colours; + subpixelorder = p_subpixelorder; + size = new_size; + } + + if(new_buffer != buffer) + (*fptr_imgbufcpy)(buffer, new_buffer, size); + +} + +void Image::Assign( const Image &image ) { + unsigned int new_size = (image.width * image.height) * image.colours; + + if(image.buffer == NULL) { + Error("Attempt to assign image with an empty buffer"); + return; + } + + if(image.colours != ZM_COLOUR_GRAY8 && image.colours != ZM_COLOUR_RGB24 && image.colours != ZM_COLOUR_RGB32) { + Error("Attempt to assign image with unexpected colours per pixel: %d",image.colours); + return; + } + + if ( !buffer || image.width != width || image.height != height || image.colours != colours || image.subpixelorder != subpixelorder) { + + if (holdbuffer && buffer) { + if (new_size > allocation) { + Error("Held buffer is undersized for assigned buffer"); + return; + } + } else { + if(new_size > allocation || !buffer) { + DumpImgBuffer(); + AllocImgBuffer(new_size); + } + } + + width = image.width; + height = image.height; + pixels = width*height; + colours = image.colours; + subpixelorder = image.subpixelorder; + size = new_size; + } + + if(image.buffer != buffer) + (*fptr_imgbufcpy)(buffer, image.buffer, size); +} + +Image *Image::HighlightEdges( Rgb colour, int p_colours, int p_subpixelorder, const Box *limits ) +{ + if ( colours != ZM_COLOUR_GRAY8 ) + { + Panic( "Attempt to highlight image edges when colours = %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,p_subpixelorder); + + /* Create a new image of the target format */ + Image *high_image = new Image( width, height, p_colours, p_subpixelorder ); + uint8_t* high_buff = high_image->WriteBuffer(width, height, p_colours, p_subpixelorder); + + /* Set image to all black */ + high_image->Clear(); + + int lo_x = limits?limits->Lo().X():0; + int lo_y = limits?limits->Lo().Y():0; + int hi_x = limits?limits->Hi().X():width-1; + int hi_y = limits?limits->Hi().Y():height-1; + + if ( p_colours == ZM_COLOUR_GRAY8 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + uint8_t* phigh = high_buff + (y * width) + lo_x; + for ( int x = lo_x; x <= hi_x; x++, p++, phigh++ ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + *phigh = colour; + } + } + } + } + else if ( p_colours == ZM_COLOUR_RGB24 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + uint8_t* phigh = high_buff + (((y * width) + lo_x) * 3); + for ( int x = lo_x; x <= hi_x; x++, p++, phigh += 3 ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + RED_PTR_RGBA(phigh) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(phigh) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(phigh) = BLUE_VAL_RGBA(colour); + } + } + } + } + else if ( p_colours == ZM_COLOUR_RGB32 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + const uint8_t* p = buffer + (y * width) + lo_x; + Rgb* phigh = (Rgb*)(high_buff + (((y * width) + lo_x) * 4)); + for ( int x = lo_x; x <= hi_x; x++, p++, phigh++ ) + { + bool edge = false; + if ( *p ) + { + if ( !edge && x > 0 && !*(p-1) ) edge = true; + if ( !edge && x < (width-1) && !*(p+1) ) edge = true; + if ( !edge && y > 0 && !*(p-width) ) edge = true; + if ( !edge && y < (height-1) && !*(p+width) ) edge = true; + } + if ( edge ) + { + *phigh = colour; + } + } + } + } + + return( high_image ); +} + +bool Image::ReadRaw( const char *filename ) +{ + FILE *infile; + if ( (infile = fopen( filename, "rb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } + + struct stat statbuf; + if ( fstat( fileno(infile), &statbuf ) < 0 ) + { + Error( "Can't fstat %s: %s", filename, strerror(errno) ); + return( false ); + } + + if ( statbuf.st_size != size ) + { + Error( "Raw file size mismatch, expected %d bytes, found %ld", size, statbuf.st_size ); + return( false ); + } + + if ( fread( buffer, size, 1, infile ) < 1 ) + { + Fatal( "Unable to read from '%s': %s", filename, strerror(errno) ); + return( false ); + } + + fclose( infile ); + + return( true ); +} + +bool Image::WriteRaw( const char *filename ) const +{ + FILE *outfile; + if ( (outfile = fopen( filename, "wb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } + + if ( fwrite( buffer, size, 1, outfile ) != 1 ) + { + Error( "Unable to write to '%s': %s", filename, strerror(errno) ); + return( false ); + } + + fclose( outfile ); + + return( true ); +} + +bool Image::ReadJpeg( const char *filename, int p_colours, int p_subpixelorder) +{ + struct jpeg_decompress_struct *cinfo = jpg_dcinfo; + + if ( !cinfo ) + { + cinfo = jpg_dcinfo = new jpeg_decompress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_decompress( cinfo ); + } + + FILE *infile; + if ( (infile = fopen( filename, "rb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } + + if ( setjmp( jpg_err.setjmp_buffer ) ) + { + jpeg_abort_decompress( cinfo ); + fclose( infile ); + return( false ); + } + + jpeg_stdio_src( cinfo, infile ); + + jpeg_read_header( cinfo, TRUE ); + + /* Check if the image has at least one huffman table defined. If not, use the standard ones */ + /* This is required for the MJPEG capture palette of USB devices */ + if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { + zm_use_std_huff_tables(cinfo); + } + + if ( cinfo->image_width != (unsigned int)width || cinfo->image_height != (unsigned int)height) + { + width = cinfo->image_width; + height = cinfo->image_height; + pixels = width*height; + } + + if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) + { + Error( "Unexpected colours when reading jpeg image: %d", colours ); + jpeg_abort_decompress( cinfo ); + fclose( infile ); + return( false ); + } + + switch(p_colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->out_color_space = JCS_GRAYSCALE; + colours = ZM_COLOUR_GRAY8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + break; + } + case ZM_COLOUR_RGB32: + { +#ifdef JCS_EXTENSIONS + colours = ZM_COLOUR_RGB32; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->out_color_space = JCS_EXT_BGRX; + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->out_color_space = JCS_EXT_XRGB; + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->out_color_space = JCS_EXT_XBGR; + subpixelorder = ZM_SUBPIX_ORDER_ABGR; + } else { + /* Assume RGBA */ + cinfo->out_color_space = JCS_EXT_RGBX; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } + break; +#else + Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); +#endif + } + case ZM_COLOUR_RGB24: + default: + { + colours = ZM_COLOUR_RGB24; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; + subpixelorder = ZM_SUBPIX_ORDER_BGR; +#else + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; + subpixelorder = ZM_SUBPIX_ORDER_RGB; +#endif + } else { + /* Assume RGB */ +/* +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_RGB; +#else + cinfo->out_color_space = JCS_RGB; +#endif +*/ + cinfo->out_color_space = JCS_RGB; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } + break; + } + } + + size = pixels*colours; + + if(buffer == NULL) { + AllocImgBuffer(size); + } else { + if(allocation < (unsigned int)size) { + if(holdbuffer) { + Error("Held buffer is undersized for the requested image"); + return (false); + } else { + DumpImgBuffer(); + AllocImgBuffer(size); + } + } + } + + jpeg_start_decompress( cinfo ); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = width * colours; /* physical row width in buffer */ + while ( cinfo->output_scanline < cinfo->output_height ) + { + row_pointer = &buffer[cinfo->output_scanline * row_stride]; + jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + } + + jpeg_finish_decompress( cinfo ); + + fclose( infile ); + + return( true ); +} + +bool Image::WriteJpeg( const char *filename, int quality_override ) const +{ + if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) + { + Image temp_image( *this ); + temp_image.Colourise( ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + return( temp_image.WriteJpeg( filename, quality_override ) ); + } + + int quality = quality_override?quality_override:config.jpeg_file_quality; + + struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; + + if ( !cinfo ) + { + cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_compress( cinfo ); + } + + FILE *outfile; + if ( (outfile = fopen( filename, "wb" )) == NULL ) + { + Error( "Can't open %s: %s", filename, strerror(errno) ); + return( false ); + } + jpeg_stdio_dest( cinfo, outfile ); + + cinfo->image_width = width; /* image width and height, in pixels */ + cinfo->image_height = height; + + switch(colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + break; + } + case ZM_COLOUR_RGB32: + { +#ifdef JCS_EXTENSIONS + cinfo->input_components = 4; + if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->in_color_space = JCS_EXT_BGRX; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->in_color_space = JCS_EXT_XRGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->in_color_space = JCS_EXT_XBGR; + } else { + /* Assume RGBA */ + cinfo->in_color_space = JCS_EXT_RGBX; + } +#else + Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); + jpeg_abort_compress( cinfo ); + fclose(outfile); + return(false); +#endif + break; + } + case ZM_COLOUR_RGB24: + default: + { + cinfo->input_components = 3; + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->in_color_space = JCS_EXT_BGR; +#else + Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); + jpeg_abort_compress( cinfo ); + fclose(outfile); + return(false); +#endif + } else { + /* Assume RGB */ +/* +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_RGB; +#else + cinfo->out_color_space = JCS_RGB; +#endif +*/ + cinfo->in_color_space = JCS_RGB; + } + break; + } + } + + jpeg_set_defaults( cinfo ); + jpeg_set_quality( cinfo, quality, false ); + cinfo->dct_method = JDCT_FASTEST; + + jpeg_start_compress( cinfo, TRUE ); + if ( config.add_jpeg_comments && text[0] ) + { + jpeg_write_marker( cinfo, JPEG_COM, (const JOCTET *)text, strlen(text) ); + } + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ + while ( cinfo->next_scanline < cinfo->image_height ) + { + row_pointer = &buffer[cinfo->next_scanline * row_stride]; + jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + } + + jpeg_finish_compress( cinfo ); + + fclose( outfile ); + + return( true ); +} + +bool Image::DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, int p_colours, int p_subpixelorder) +{ + struct jpeg_decompress_struct *cinfo = jpg_dcinfo; + + if ( !cinfo ) + { + cinfo = jpg_dcinfo = new jpeg_decompress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_decompress( cinfo ); + } + + if ( setjmp( jpg_err.setjmp_buffer ) ) + { + jpeg_abort_decompress( cinfo ); + return( false ); + } + + zm_jpeg_mem_src( cinfo, inbuffer, inbuffer_size ); + + jpeg_read_header( cinfo, TRUE ); + + /* Check if the image has at least one huffman table defined. If not, use the standard ones */ + /* This is required for the MJPEG capture palette of USB devices */ + if(cinfo->dc_huff_tbl_ptrs[0] == NULL) { + zm_use_std_huff_tables(cinfo); + } + + if ( cinfo->image_width != (unsigned int)width || cinfo->image_height != (unsigned int)height) + { + width = cinfo->image_width; + height = cinfo->image_height; + pixels = width*height; + } + + if ( cinfo->num_components != 1 && cinfo->num_components != 3 ) + { + Error( "Unexpected colours when reading jpeg image: %d", colours ); + jpeg_abort_decompress( cinfo ); + return( false ); + } + + switch(p_colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->out_color_space = JCS_GRAYSCALE; + colours = ZM_COLOUR_GRAY8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + break; + } + case ZM_COLOUR_RGB32: + { +#ifdef JCS_EXTENSIONS + colours = ZM_COLOUR_RGB32; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->out_color_space = JCS_EXT_BGRX; + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->out_color_space = JCS_EXT_XRGB; + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else if(p_subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->out_color_space = JCS_EXT_XBGR; + subpixelorder = ZM_SUBPIX_ORDER_ABGR; + } else { + /* Assume RGBA */ + cinfo->out_color_space = JCS_EXT_RGBX; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } + break; +#else + Warning("libjpeg-turbo is required for reading a JPEG directly into a RGB32 buffer, reading into a RGB24 buffer instead."); +#endif + } + case ZM_COLOUR_RGB24: + default: + { + colours = ZM_COLOUR_RGB24; + if(p_subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_BGR; + subpixelorder = ZM_SUBPIX_ORDER_BGR; +#else + Warning("libjpeg-turbo is required for reading a JPEG directly into a BGR24 buffer, reading into a RGB24 buffer instead."); + cinfo->out_color_space = JCS_RGB; + subpixelorder = ZM_SUBPIX_ORDER_RGB; +#endif + } else { + /* Assume RGB */ +/* +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_RGB; +#else + cinfo->out_color_space = JCS_RGB; +#endif +*/ + cinfo->out_color_space = JCS_RGB; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } + break; + } + } + + size = pixels*colours; + + if(buffer == NULL) { + AllocImgBuffer(size); + } else { + if(allocation < (unsigned int)size) { + if(holdbuffer) { + Error("Held buffer is undersized for the requested image"); + return (false); + } else { + DumpImgBuffer(); + AllocImgBuffer(size); + } + } + } + + jpeg_start_decompress( cinfo ); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = width * colours; /* physical row width in buffer */ + while ( cinfo->output_scanline < cinfo->output_height ) + { + row_pointer = &buffer[cinfo->output_scanline * row_stride]; + jpeg_read_scanlines( cinfo, &row_pointer, 1 ); + } + + jpeg_finish_decompress( cinfo ); + + return( true ); +} + +bool Image::EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override ) const +{ + if ( config.colour_jpeg_files && colours == ZM_COLOUR_GRAY8 ) + { + Image temp_image( *this ); + temp_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + return( temp_image.EncodeJpeg( outbuffer, outbuffer_size, quality_override ) ); + } + + int quality = quality_override?quality_override:config.jpeg_stream_quality; + + struct jpeg_compress_struct *cinfo = jpg_ccinfo[quality]; + + if ( !cinfo ) + { + cinfo = jpg_ccinfo[quality] = new jpeg_compress_struct; + cinfo->err = jpeg_std_error( &jpg_err.pub ); + jpg_err.pub.error_exit = zm_jpeg_error_exit; + jpg_err.pub.emit_message = zm_jpeg_emit_message; + jpeg_create_compress( cinfo ); + } + + zm_jpeg_mem_dest( cinfo, outbuffer, outbuffer_size ); + + cinfo->image_width = width; /* image width and height, in pixels */ + cinfo->image_height = height; + + switch(colours) { + case ZM_COLOUR_GRAY8: + { + cinfo->input_components = 1; + cinfo->in_color_space = JCS_GRAYSCALE; + break; + } + case ZM_COLOUR_RGB32: + { +#ifdef JCS_EXTENSIONS + cinfo->input_components = 4; + if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + cinfo->in_color_space = JCS_EXT_BGRX; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + cinfo->in_color_space = JCS_EXT_XRGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + cinfo->in_color_space = JCS_EXT_XBGR; + } else { + /* Assume RGBA */ + cinfo->in_color_space = JCS_EXT_RGBX; + } +#else + Error("libjpeg-turbo is required for JPEG encoding directly from RGB32 source"); + jpeg_abort_compress( cinfo ); + return(false); +#endif + break; + } + case ZM_COLOUR_RGB24: + default: + { + cinfo->input_components = 3; + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { +#ifdef JCS_EXTENSIONS + cinfo->in_color_space = JCS_EXT_BGR; +#else + Error("libjpeg-turbo is required for JPEG encoding directly from BGR24 source"); + jpeg_abort_compress( cinfo ); + return(false); +#endif + } else { + /* Assume RGB */ +/* +#ifdef JCS_EXTENSIONS + cinfo->out_color_space = JCS_EXT_RGB; +#else + cinfo->out_color_space = JCS_RGB; +#endif +*/ + cinfo->in_color_space = JCS_RGB; + } + break; + } + } + + jpeg_set_defaults( cinfo ); + jpeg_set_quality( cinfo, quality, false ); + cinfo->dct_method = JDCT_FASTEST; + + jpeg_start_compress( cinfo, TRUE ); + + JSAMPROW row_pointer; /* pointer to a single row */ + int row_stride = cinfo->image_width * colours; /* physical row width in buffer */ + while ( cinfo->next_scanline < cinfo->image_height ) + { + row_pointer = &buffer[cinfo->next_scanline * row_stride]; + jpeg_write_scanlines( cinfo, &row_pointer, 1 ); + } + + jpeg_finish_compress( cinfo ); + + return( true ); +} + +#if HAVE_ZLIB_H +bool Image::Unzip( const Bytef *inbuffer, unsigned long inbuffer_size ) +{ + unsigned long zip_size = size; + int result = uncompress( buffer, &zip_size, inbuffer, inbuffer_size ); + if ( result != Z_OK ) + { + Error( "Unzip failed, result = %d", result ); + return( false ); + } + if ( zip_size != (unsigned int)size ) + { + Error( "Unzip failed, size mismatch, expected %d bytes, got %ld", size, zip_size ); + return( false ); + } + return( true ); +} + +bool Image::Zip( Bytef *outbuffer, unsigned long *outbuffer_size, int compression_level ) const +{ + int result = compress2( outbuffer, outbuffer_size, buffer, size, compression_level ); + if ( result != Z_OK ) + { + Error( "Zip failed, result = %d", result ); + return( false ); + } + return( true ); +} +#endif // HAVE_ZLIB_H + +bool Image::Crop( int lo_x, int lo_y, int hi_x, int hi_y ) +{ + int new_width = (hi_x-lo_x)+1; + int new_height = (hi_y-lo_y)+1; + + if ( lo_x > hi_x || lo_y > hi_y ) + { + Error( "Invalid or reversed crop region %d,%d -> %d,%d", lo_x, lo_y, hi_x, hi_y ); + return( false ); + } + if ( lo_x < 0 || hi_x > (width-1) || ( lo_y < 0 || hi_y > (height-1) ) ) + { + Error( "Attempting to crop outside image, %d,%d -> %d,%d not in %d,%d", lo_x, lo_y, hi_x, hi_y, width-1, height-1 ); + return( false ); + } + + if ( new_width == width && new_height == height ) + { + return( true ); + } + + int new_size = new_width*new_height*colours; + uint8_t *new_buffer = AllocBuffer(new_size); + + int new_stride = new_width*colours; + for ( int y = lo_y, ny = 0; y <= hi_y; y++, ny++ ) + { + unsigned char *pbuf = &buffer[((y*width)+lo_x)*colours]; + unsigned char *pnbuf = &new_buffer[(ny*new_width)*colours]; + memcpy( pnbuf, pbuf, new_stride ); + } + + AssignDirect(new_width, new_height, colours, subpixelorder, new_buffer, new_size, ZM_BUFTYPE_ZM); + + return( true ); +} + +bool Image::Crop( const Box &limits ) +{ + return( Crop( limits.LoX(), limits.LoY(), limits.HiX(), limits.HiY() ) ); +} + +/* Far from complete */ +/* Need to implement all possible of overlays possible */ +void Image::Overlay( const Image &image ) +{ + if ( !(width == image.width && height == image.height) ) + { + Panic( "Attempt to overlay different sized images, expected %dx%d, got %dx%d", width, height, image.width, image.height ); + } + + if( colours == image.colours && subpixelorder != image.subpixelorder ) { + Warning("Attempt to overlay images of same format but with different subpixel order."); + } + + /* Grayscale ontop of grayscale - complete */ + if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_GRAY8 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( *psrc ) + { + *pdest = *psrc; + } + pdest++; + psrc++; + } + + /* RGB24 ontop of grayscale - convert to same format first - complete */ + } else if ( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB24 ) { + Colourise(image.colours, image.subpixelorder); + + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) + { + RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); + GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); + BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); + } + pdest += 3; + psrc += 3; + } + + /* RGB32 ontop of grayscale - convert to same format first - complete */ + } else if( colours == ZM_COLOUR_GRAY8 && image.colours == ZM_COLOUR_RGB32 ) { + Colourise(image.colours, image.subpixelorder); + + const Rgb* const max_ptr = (Rgb*)(buffer+size); + const Rgb* prsrc = (Rgb*)image.buffer; + Rgb* prdest = (Rgb*)buffer; + + if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } + + /* Grayscale ontop of RGB24 - complete */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_GRAY8 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( *psrc ) + { + RED_PTR_RGBA(pdest) = GREEN_PTR_RGBA(pdest) = BLUE_PTR_RGBA(pdest) = *psrc; + } + pdest += 3; + psrc++; + } + + /* RGB24 ontop of RGB24 - not complete. need to take care of different subpixel orders */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB24 ) { + const uint8_t* const max_ptr = buffer+size; + const uint8_t* psrc = image.buffer; + uint8_t* pdest = buffer; + + while( pdest < max_ptr ) + { + if ( RED_PTR_RGBA(psrc) || GREEN_PTR_RGBA(psrc) || BLUE_PTR_RGBA(psrc) ) + { + RED_PTR_RGBA(pdest) = RED_PTR_RGBA(psrc); + GREEN_PTR_RGBA(pdest) = GREEN_PTR_RGBA(psrc); + BLUE_PTR_RGBA(pdest) = BLUE_PTR_RGBA(psrc); + } + pdest += 3; + psrc += 3; + } + + /* RGB32 ontop of RGB24 - TO BE DONE */ + } else if ( colours == ZM_COLOUR_RGB24 && image.colours == ZM_COLOUR_RGB32 ) { + Error("Overlay of RGB32 ontop of RGB24 is not supported."); + + /* Grayscale ontop of RGB32 - complete */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_GRAY8 ) { + const Rgb* const max_ptr = (Rgb*)(buffer+size); + Rgb* prdest = (Rgb*)buffer; + const uint8_t* psrc = image.buffer; + + if(subpixelorder == ZM_SUBPIX_ORDER_RGBA || subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( *psrc ) + { + RED_PTR_RGBA(prdest) = GREEN_PTR_RGBA(prdest) = BLUE_PTR_RGBA(prdest) = *psrc; + } + prdest++; + psrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( *psrc ) + { + RED_PTR_ABGR(prdest) = GREEN_PTR_ABGR(prdest) = BLUE_PTR_ABGR(prdest) = *psrc; + } + prdest++; + psrc++; + } + } + + /* RGB24 ontop of RGB32 - TO BE DONE */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB24 ) { + Error("Overlay of RGB24 ontop of RGB32 is not supported."); + + /* RGB32 ontop of RGB32 - not complete. need to take care of different subpixel orders */ + } else if ( colours == ZM_COLOUR_RGB32 && image.colours == ZM_COLOUR_RGB32 ) { + const Rgb* const max_ptr = (Rgb*)(buffer+size); + Rgb* prdest = (Rgb*)buffer; + const Rgb* prsrc = (Rgb*)image.buffer; + + if(image.subpixelorder == ZM_SUBPIX_ORDER_RGBA || image.subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* RGB\BGR\RGBA\BGRA subpixel order - Alpha byte is last */ + while (prdest < max_ptr) { + if ( RED_PTR_RGBA(prsrc) || GREEN_PTR_RGBA(prsrc) || BLUE_PTR_RGBA(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } else { + /* ABGR\ARGB subpixel order - Alpha byte is first */ + while (prdest < max_ptr) { + if ( RED_PTR_ABGR(prsrc) || GREEN_PTR_ABGR(prsrc) || BLUE_PTR_ABGR(prsrc) ) + { + *prdest = *prsrc; + } + prdest++; + prsrc++; + } + } + } + +} + +/* RGB32 compatible: complete */ +void Image::Overlay( const Image &image, int x, int y ) +{ + if ( !(width < image.width || height < image.height) ) + { + Panic( "Attempt to overlay image too big for destination, %dx%d > %dx%d", image.width, image.height, width, height ); + } + + if ( !(width < (x+image.width) || height < (y+image.height)) ) + { + Panic( "Attempt to overlay image outside of destination bounds, %dx%d @ %dx%d > %dx%d", image.width, image.height, x, y, width, height ); + } + + if ( !(colours == image.colours) ) + { + Panic( "Attempt to partial overlay differently coloured images, expected %d, got %d", colours, image.colours ); + } + + int lo_x = x; + int lo_y = y; + int hi_x = (x+image.width)-1; + int hi_y = (y+image.height-1); + if ( colours == ZM_COLOUR_GRAY8 ) + { + const uint8_t *psrc = image.buffer; + for ( int y = lo_y; y <= hi_y; y++ ) + { + uint8_t *pdest = &buffer[(y*width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + const uint8_t *psrc = image.buffer; + for ( int y = lo_y; y <= hi_y; y++ ) + { + uint8_t *pdest = &buffer[colours*((y*width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + *pdest++ = *psrc++; + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + const Rgb *psrc = (Rgb*)(image.buffer); + for ( int y = lo_y; y <= hi_y; y++ ) + { + Rgb *pdest = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + for ( int x = lo_x; x <= hi_x; x++ ) + { + *pdest++ = *psrc++; + } + } + } else { + Error("Overlay called with unexpected colours: %d", colours); + } + +} + +void Image::Blend( const Image &image, int transparency ) +{ +#ifdef ZM_IMAGE_PROFILING + struct timespec start,end,diff; + unsigned long long executetime; + unsigned long milpixels; +#endif + uint8_t* new_buffer; + + if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) + { + Panic( "Attempt to blend different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder ); + } + + if(transparency <= 0) + return; + + new_buffer = AllocBuffer(size); + +#ifdef ZM_IMAGE_PROFILING + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); +#endif + + /* Do the blending */ + (*fptr_blend)(buffer, image.buffer, new_buffer, size, transparency); + +#ifdef ZM_IMAGE_PROFILING + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); + timespec_diff(&start,&end,&diff); + + executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; + milpixels = (unsigned long)((long double)size)/((((long double)executetime)/1000)); + Debug(5, "Blend: %u colours blended in %llu nanoseconds, %lu million colours/s\n",size,executetime,milpixels); +#endif + + AssignDirect( width, height, colours, subpixelorder, new_buffer, size, ZM_BUFTYPE_ZM); +} + +Image *Image::Merge( int n_images, Image *images[] ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } + + Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder); + int size = result->size; + for ( int i = 0; i < size; i++ ) + { + int total = 0; + uint8_t *pdest = result->buffer; + for ( int j = 0; j < n_images; j++ ) + { + uint8_t *psrc = images[j]->buffer; + total += *psrc; + psrc++; + } + *pdest = total/n_images; + pdest++; + } + return( result ); +} + +Image *Image::Merge( int n_images, Image *images[], double weight ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to merge different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } + + Image *result = new Image( *images[0] ); + int size = result->size; + double factor = 1.0*weight; + for ( int i = 1; i < n_images; i++ ) + { + uint8_t *pdest = result->buffer; + uint8_t *psrc = images[i]->buffer; + for ( int j = 0; j < size; j++ ) + { + *pdest = (uint8_t)(((*pdest)*(1.0-factor))+((*psrc)*factor)); + pdest++; + psrc++; + } + factor *= weight; + } + return( result ); +} + +Image *Image::Highlight( int n_images, Image *images[], const Rgb threshold, const Rgb ref_colour ) +{ + if ( n_images <= 0 ) return( 0 ); + if ( n_images == 1 ) return( new Image( *images[0] ) ); + + int width = images[0]->width; + int height = images[0]->height; + int colours = images[0]->colours; + for ( int i = 1; i < n_images; i++ ) + { + if ( !(width == images[i]->width && height == images[i]->height && colours == images[i]->colours) ) + { + Panic( "Attempt to highlight different sized images, expected %dx%dx%d, got %dx%dx%d, for image %d", width, height, colours, images[i]->width, images[i]->height, images[i]->colours, i ); + } + } + + Image *result = new Image( width, height, images[0]->colours, images[0]->subpixelorder ); + int size = result->size; + for ( int c = 0; c < colours; c++ ) + { + for ( int i = 0; i < size; i++ ) + { + int count = 0; + uint8_t *pdest = result->buffer+c; + for ( int j = 0; j < n_images; j++ ) + { + uint8_t *psrc = images[j]->buffer+c; + + if ( (unsigned)abs((*psrc)-RGB_VAL(ref_colour,c)) >= RGB_VAL(threshold,c) ) + { + count++; + } + psrc += colours; + } + *pdest = (count*255)/n_images; + pdest += 3; + } + } + return( result ); +} + +/* New function to allow buffer re-using instead of allocationg memory for the delta image everytime */ +void Image::Delta( const Image &image, Image* targetimage) const +{ +#ifdef ZM_IMAGE_PROFILING + struct timespec start,end,diff; + unsigned long long executetime; + unsigned long milpixels; +#endif + + if ( !(width == image.width && height == image.height && colours == image.colours && subpixelorder == image.subpixelorder) ) + { + Panic( "Attempt to get delta of different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, image.width, image.height, image.colours, image.subpixelorder); + } + + uint8_t *pdiff = targetimage->WriteBuffer(width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE); + + if(pdiff == NULL) { + Panic("Failed requesting writeable buffer for storing the delta image"); + } + +#ifdef ZM_IMAGE_PROFILING + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&start); +#endif + + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + (*fptr_delta8_bgr)(buffer, image.buffer, pdiff, pixels); + } else { + /* Assume RGB subpixel order */ + (*fptr_delta8_rgb)(buffer, image.buffer, pdiff, pixels); + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + (*fptr_delta8_argb)(buffer, image.buffer, pdiff, pixels); + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + (*fptr_delta8_abgr)(buffer, image.buffer, pdiff, pixels); + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + (*fptr_delta8_bgra)(buffer, image.buffer, pdiff, pixels); + } else { + /* Assume RGBA subpixel order */ + (*fptr_delta8_rgba)(buffer, image.buffer, pdiff, pixels); + } + break; + } + case ZM_COLOUR_GRAY8: + (*fptr_delta8_gray8)(buffer, image.buffer, pdiff, pixels); + break; + default: + Panic("Delta called with unexpected colours: %d",colours); + break; + } + +#ifdef ZM_IMAGE_PROFILING + clock_gettime(CLOCK_THREAD_CPUTIME_ID,&end); + timespec_diff(&start,&end,&diff); + + executetime = (1000000000ull * diff.tv_sec) + diff.tv_nsec; + milpixels = (unsigned long)((long double)pixels)/((((long double)executetime)/1000)); + Debug(5, "Delta: %u delta pixels generated in %llu nanoseconds, %lu million pixels/s\n",pixels,executetime,milpixels); +#endif +} + +const Coord Image::centreCoord( const char *text ) const +{ + int index = 0; + int line_no = 0; + int text_len = strlen( text ); + int line_len = 0; + int max_line_len = 0; + const char *line = text; + + while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + { + if ( line_len > max_line_len ) + max_line_len = line_len; + + index += line_len; + while ( text[index] == '\n' ) + { + index++; + } + line = text+index; + line_no++; + } + int x = (width - (max_line_len * CHAR_WIDTH) ) / 2; + int y = (height - (line_no * LINE_HEIGHT) ) / 2; + return( Coord( x, y ) ); +} + +/* RGB32 compatible: complete */ +void Image::Annotate( const char *p_text, const Coord &coord, const Rgb fg_colour, const Rgb bg_colour ) +{ + strncpy( text, p_text, sizeof(text) ); + + int index = 0; + int line_no = 0; + int text_len = strlen( text ); + int line_len = 0; + const char *line = text; + + const uint8_t fg_r_col = RED_VAL_RGBA(fg_colour); + const uint8_t fg_g_col = GREEN_VAL_RGBA(fg_colour); + const uint8_t fg_b_col = BLUE_VAL_RGBA(fg_colour); + const uint8_t fg_bw_col = fg_colour & 0xff; + const Rgb fg_rgb_col = rgb_convert(fg_colour,subpixelorder); + const bool fg_trans = (fg_colour == RGB_TRANSPARENT); + + const uint8_t bg_r_col = RED_VAL_RGBA(bg_colour); + const uint8_t bg_g_col = GREEN_VAL_RGBA(bg_colour); + const uint8_t bg_b_col = BLUE_VAL_RGBA(bg_colour); + const uint8_t bg_bw_col = bg_colour & 0xff; + const Rgb bg_rgb_col = rgb_convert(bg_colour,subpixelorder); + const bool bg_trans = (bg_colour == RGB_TRANSPARENT); + + while ( (index < text_len) && (line_len = strcspn( line, "\n" )) ) + { + + int line_width = line_len * CHAR_WIDTH; + + int lo_line_x = coord.X(); + int lo_line_y = coord.Y() + (line_no * LINE_HEIGHT); + + int min_line_x = 0; + int max_line_x = width - line_width; + int min_line_y = 0; + int max_line_y = height - LINE_HEIGHT; + + if ( lo_line_x > max_line_x ) + lo_line_x = max_line_x; + if ( lo_line_x < min_line_x ) + lo_line_x = min_line_x; + if ( lo_line_y > max_line_y ) + lo_line_y = max_line_y; + if ( lo_line_y < min_line_y ) + lo_line_y = min_line_y; + + int hi_line_x = lo_line_x + line_width; + int hi_line_y = lo_line_y + LINE_HEIGHT; + + // Clip anything that runs off the right of the screen + if ( hi_line_x > width ) + hi_line_x = width; + if ( hi_line_y > height ) + hi_line_y = height; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + unsigned char *ptr = &buffer[(lo_line_y*width)+lo_line_x]; + for ( int y = lo_line_y, r = 0; y < hi_line_y && r < CHAR_HEIGHT; y++, r++, ptr += width ) + { + unsigned char *temp_ptr = ptr; + for ( int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) + { + int f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( int i = 0; i < CHAR_WIDTH && x < hi_line_x; i++, x++, temp_ptr++ ) + { + if ( f & (0x80 >> i) ) + { + if ( !fg_trans ) + *temp_ptr = fg_bw_col; + } + else if ( !bg_trans ) + { + *temp_ptr = bg_bw_col; + } + } + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + int wc = width * colours; + + unsigned char *ptr = &buffer[((lo_line_y*width)+lo_line_x)*colours]; + for ( int y = lo_line_y, r = 0; y < hi_line_y && r < CHAR_HEIGHT; y++, r++, ptr += wc ) + { + unsigned char *temp_ptr = ptr; + for ( int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) + { + int f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( int i = 0; i < CHAR_WIDTH && x < hi_line_x; i++, x++, temp_ptr += colours ) + { + if ( f & (0x80 >> i) ) + { + if ( !fg_trans ) + { + RED_PTR_RGBA(temp_ptr) = fg_r_col; + GREEN_PTR_RGBA(temp_ptr) = fg_g_col; + BLUE_PTR_RGBA(temp_ptr) = fg_b_col; + } + } + else if ( !bg_trans ) + { + RED_PTR_RGBA(temp_ptr) = bg_r_col; + GREEN_PTR_RGBA(temp_ptr) = bg_g_col; + BLUE_PTR_RGBA(temp_ptr) = bg_b_col; + } + } + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + int wc = width * colours; + + uint8_t *ptr = &buffer[((lo_line_y*width)+lo_line_x)<<2]; + for ( int y = lo_line_y, r = 0; y < hi_line_y && r < CHAR_HEIGHT; y++, r++, ptr += wc ) + { + Rgb* temp_ptr = (Rgb*)ptr; + for ( int x = lo_line_x, c = 0; x < hi_line_x && c < line_len; c++ ) + { + int f = fontdata[(line[c] * CHAR_HEIGHT) + r]; + for ( int i = 0; i < CHAR_WIDTH && x < hi_line_x; i++, x++, temp_ptr++ ) + { + if ( f & (0x80 >> i) ) + { + if ( !fg_trans ) + { + *temp_ptr = fg_rgb_col; + } + } + else if ( !bg_trans ) + { + *temp_ptr = bg_rgb_col; + } + } + } + } + + } else { + Panic("Annontate called with unexpected colours: %d",colours); + return; + } + + index += line_len; + while ( text[index] == '\n' ) + { + index++; + } + line = text+index; + line_no++; + } +} + +void Image::Timestamp( const char *label, const time_t when, const Coord &coord ) +{ + char time_text[64]; + strftime( time_text, sizeof(time_text), "%y/%m/%d %H:%M:%S", localtime( &when ) ); + char text[64]; + if ( label ) + { + snprintf( text, sizeof(text), "%s - %s", label, time_text ); + Annotate( text, coord ); + } + else + { + Annotate( time_text, coord ); + } +} + +/* RGB32 compatible: complete */ +void Image::Colourise(const int p_reqcolours, const int p_reqsubpixelorder) +{ + Debug(9, "Colourise: Req colours: %u Req subpixel order: %u Current colours: %u Current subpixel order: %u",p_reqcolours,p_reqsubpixelorder,colours,subpixelorder); + + if ( colours != ZM_COLOUR_GRAY8) { + Warning("Target image is already colourised, colours: %u",colours); + return; + } + + if ( p_reqcolours == ZM_COLOUR_RGB32 ) { + /* RGB32 */ + Rgb* new_buffer = (Rgb*)AllocBuffer(pixels*sizeof(Rgb)); + + const uint8_t *psrc = buffer; + Rgb* pdest = new_buffer; + Rgb subpixel; + Rgb newpixel; + + if ( p_reqsubpixelorder == ZM_SUBPIX_ORDER_ABGR || p_reqsubpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB\ABGR subpixel order. alpha byte is first (mem+0), so we need to shift the pixel left in the end */ + for(int i=0;iLo().X():0; + int lo_y = limits?limits->Lo().Y():0; + int hi_x = limits?limits->Hi().X():width-1; + int hi_y = limits?limits->Hi().Y():height-1; + if ( colours == ZM_COLOUR_GRAY8 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + *p = colour; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++, p += 3) + { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ + { + for ( unsigned int y = lo_y; y <= (unsigned int)hi_y; y++ ) + { + Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + + for ( unsigned int x = lo_x; x <= (unsigned int)hi_x; x++, p++) + { + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } +} + +/* RGB32 compatible: complete */ +void Image::Fill( Rgb colour, int density, const Box *limits ) +{ + /* Allow the faster version to be used if density is not used (density=1) */ + if(density <= 1) + return Fill(colour,limits); + + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) + { + Panic( "Attempt to fill image with unexpected colours %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,subpixelorder); + + int lo_x = limits?limits->Lo().X():0; + int lo_y = limits?limits->Lo().Y():0; + int hi_x = limits?limits->Hi().X():width-1; + int hi_y = limits?limits->Hi().Y():height-1; + if ( colours == ZM_COLOUR_GRAY8 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) + *p = colour; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++, p += 3) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) /* RGB32 */ + { + for ( int y = lo_y; y <= hi_y; y++ ) + { + Rgb* p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( ( x == lo_x || x == hi_x || y == lo_y || y == hi_y ) || (!(x%density) && !(y%density) ) ) + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } + +} + +/* RGB32 compatible: complete */ +void Image::Outline( Rgb colour, const Polygon &polygon ) +{ + if ( !(colours == ZM_COLOUR_GRAY8 || colours == ZM_COLOUR_RGB24 || colours == ZM_COLOUR_RGB32 ) ) + { + Panic( "Attempt to outline image with unexpected colours %d", colours ); + } + + /* Convert the colour's RGBA subpixel order into the image's subpixel order */ + colour = rgb_convert(colour,subpixelorder); + + int n_coords = polygon.getNumCoords(); + for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) + { + const Coord &p1 = polygon.getCoord( i ); + const Coord &p2 = polygon.getCoord( j ); + + int x1 = p1.X(); + int x2 = p2.X(); + int y1 = p1.Y(); + int y2 = p2.Y(); + + double dx = x2 - x1; + double dy = y2 - y1; + + double grad; + + Debug( 9, "dx: %.2lf, dy: %.2lf", dx, dy ); + if ( fabs(dx) <= fabs(dy) ) + { + Debug( 9, "dx <= dy" ); + if ( y1 != y2 ) + grad = dx/dy; + else + grad = width; + + double x; + int y, yinc = (y1 dy" ); + if ( x1 != x2 ) + grad = dy/dx; + else + grad = height; + Debug( 9, "grad: %.2lf", grad ); + + double y; + int x, xinc = (x1= Logger::DEBUG9 ) + { + for ( int i = 0; i < n_global_edges; i++ ) + { + Debug( 9, "%d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", i, global_edges[i].min_y, global_edges[i].max_y, global_edges[i].min_x, global_edges[i]._1_m ); + } + } +#endif + + int n_active_edges = 0; + Edge active_edges[n_global_edges]; + int y = global_edges[0].min_y; + do + { + for ( int i = 0; i < n_global_edges; i++ ) + { + if ( global_edges[i].min_y == y ) + { + Debug( 9, "Moving global edge" ); + active_edges[n_active_edges++] = global_edges[i]; + if ( i < (n_global_edges-1) ) + { + //memcpy( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); + memmove( &global_edges[i], &global_edges[i+1], sizeof(*global_edges)*(n_global_edges-i) ); + i--; + } + n_global_edges--; + } + else + { + break; + } + } + qsort( active_edges, n_active_edges, sizeof(*active_edges), Edge::CompareX ); +#ifndef ZM_DBG_OFF + if ( logLevel() >= Logger::DEBUG9 ) + { + for ( int i = 0; i < n_active_edges; i++ ) + { + Debug( 9, "%d - %d: min_y: %d, max_y:%d, min_x:%.2f, 1/m:%.2f", y, i, active_edges[i].min_y, active_edges[i].max_y, active_edges[i].min_x, active_edges[i]._1_m ); + } + } +#endif + if ( !(y%density) ) + { + //Debug( 9, "%d", y ); + for ( int i = 0; i < n_active_edges; ) + { + int lo_x = int(round(active_edges[i++].min_x)); + int hi_x = int(round(active_edges[i++].min_x)); + if( colours == ZM_COLOUR_GRAY8 ) { + unsigned char *p = &buffer[(y*width)+lo_x]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( !(x%density) ) + { + //Debug( 9, " %d", x ); + *p = colour; + } + } + } else if( colours == ZM_COLOUR_RGB24 ) { + unsigned char *p = &buffer[colours*((y*width)+lo_x)]; + for ( int x = lo_x; x <= hi_x; x++, p += 3) + { + if ( !(x%density) ) + { + RED_PTR_RGBA(p) = RED_VAL_RGBA(colour); + GREEN_PTR_RGBA(p) = GREEN_VAL_RGBA(colour); + BLUE_PTR_RGBA(p) = BLUE_VAL_RGBA(colour); + } + } + } else if( colours == ZM_COLOUR_RGB32 ) { + Rgb *p = (Rgb*)&buffer[((y*width)+lo_x)<<2]; + for ( int x = lo_x; x <= hi_x; x++, p++) + { + if ( !(x%density) ) + { + /* Fast, copies the entire pixel in a single pass */ + *p = colour; + } + } + } + } + } + y++; + for ( int i = n_active_edges-1; i >= 0; i-- ) + { + if ( y >= active_edges[i].max_y ) // Or >= as per sheets + { + Debug( 9, "Deleting active_edge" ); + if ( i < (n_active_edges-1) ) + { + //memcpy( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); + memmove( &active_edges[i], &active_edges[i+1], sizeof(*active_edges)*(n_active_edges-i) ); + } + n_active_edges--; + } + else + { + active_edges[i].min_x += active_edges[i]._1_m; + } + } + } while ( n_global_edges || n_active_edges ); +} + +void Image::Fill( Rgb colour, const Polygon &polygon ) +{ + Fill( colour, 1, polygon ); +} + +/* RGB32 compatible: complete */ +void Image::Rotate( int angle ) +{ + + angle %= 360; + + if ( !angle ) + { + return; + } + if ( angle%90 ) + { + return; + } + + unsigned int new_height = height; + unsigned int new_width = width; + uint8_t* rotate_buffer = AllocBuffer(size); + + switch( angle ) + { + case 90 : + { + new_height = width; + new_width = height; + + int line_bytes = new_width*colours; + unsigned char *s_ptr = buffer; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + unsigned char *d_ptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_ptr = rotate_buffer+i; + for ( int j = new_height-1; j >= 0; j-- ) + { + *d_ptr = *s_ptr++; + d_ptr += line_bytes; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_rptr = (Rgb*)(rotate_buffer+(i<<2)); + for ( int j = new_height-1; j >= 0; j-- ) + { + *d_rptr = *s_rptr++; + d_rptr += new_width; + } + } + } + else /* Assume RGB24 */ + { + unsigned char *d_ptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_ptr = rotate_buffer+(3*i); + for ( int j = new_height-1; j >= 0; j-- ) + { + *d_ptr = *s_ptr++; + *(d_ptr+1) = *s_ptr++; + *(d_ptr+2) = *s_ptr++; + d_ptr += line_bytes; + } + } + } + break; + } + case 180 : + { + unsigned char *s_ptr = buffer+size; + unsigned char *d_ptr = rotate_buffer; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + while( s_ptr > buffer ) + { + s_ptr--; + *d_ptr++ = *s_ptr; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr = (Rgb*)d_ptr; + while( s_rptr > (Rgb*)buffer ) + { + s_rptr--; + *d_rptr++ = *s_rptr; + } + } + else /* Assume RGB24 */ + { + while( s_ptr > buffer ) + { + s_ptr -= 3; + *d_ptr++ = *s_ptr; + *d_ptr++ = *(s_ptr+1); + *d_ptr++ = *(s_ptr+2); + } + } + break; + } + case 270 : + { + new_height = width; + new_width = height; + + int line_bytes = new_width*colours; + unsigned char *s_ptr = buffer+size; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + unsigned char *d_ptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_ptr = rotate_buffer+i; + for ( int j = new_height-1; j >= 0; j-- ) + { + s_ptr--; + *d_ptr = *s_ptr; + d_ptr += line_bytes; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_rptr = (Rgb*)(rotate_buffer+(i<<2)); + for ( int j = new_height-1; j >= 0; j-- ) + { + s_rptr--; + *d_rptr = *s_rptr; + d_rptr += new_width; + } + } + } + else /* Assume RGB24 */ + { + unsigned char *d_ptr; + for ( int i = new_width-1; i >= 0; i-- ) + { + d_ptr = rotate_buffer+(3*i); + for ( int j = new_height-1; j >= 0; j-- ) + { + *(d_ptr+2) = *(--s_ptr); + *(d_ptr+1) = *(--s_ptr); + *d_ptr = *(--s_ptr); + d_ptr += line_bytes; + } + } + } + break; + } + } + + AssignDirect( new_width, new_height, colours, subpixelorder, rotate_buffer, size, ZM_BUFTYPE_ZM); + +} + +/* RGB32 compatible: complete */ +void Image::Flip( bool leftright ) +{ + uint8_t* flip_buffer = AllocBuffer(size); + + int line_bytes = width*colours; + int line_bytes2 = 2*line_bytes; + if ( leftright ) + { + // Horizontal flip, left to right + unsigned char *s_ptr = buffer+line_bytes; + unsigned char *d_ptr = flip_buffer; + unsigned char *max_d_ptr = flip_buffer + size; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + while( d_ptr < max_d_ptr ) + { + for ( int j = 0; j < width; j++ ) + { + s_ptr--; + *d_ptr++ = *s_ptr; + } + s_ptr += line_bytes2; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + Rgb* s_rptr = (Rgb*)s_ptr; + Rgb* d_rptr = (Rgb*)flip_buffer; + Rgb* max_d_rptr = (Rgb*)max_d_ptr; + while( d_rptr < max_d_rptr ) + { + for ( int j = 0; j < width; j++ ) + { + s_rptr--; + *d_rptr++ = *s_rptr; + } + s_rptr += width * 2; + } + } + else /* Assume RGB24 */ + { + while( d_ptr < max_d_ptr ) + { + for ( int j = 0; j < width; j++ ) + { + s_ptr -= 3; + *d_ptr++ = *s_ptr; + *d_ptr++ = *(s_ptr+1); + *d_ptr++ = *(s_ptr+2); + } + s_ptr += line_bytes2; + } + } + } + else + { + // Vertical flip, top to bottom + unsigned char *s_ptr = buffer+(height*line_bytes); + unsigned char *d_ptr = flip_buffer; + + while( s_ptr > buffer ) + { + s_ptr -= line_bytes; + memcpy( d_ptr, s_ptr, line_bytes ); + d_ptr += line_bytes; + } + } + + AssignDirect( width, height, colours, subpixelorder, flip_buffer, size, ZM_BUFTYPE_ZM); + +} + +void Image::Scale( unsigned int factor ) +{ + if ( !factor ) + { + Error( "Bogus scale factor %d found", factor ); + return; + } + if ( factor == ZM_SCALE_BASE ) + { + return; + } + + unsigned int new_width = (width*factor)/ZM_SCALE_BASE; + unsigned int new_height = (height*factor)/ZM_SCALE_BASE; + + size_t scale_buffer_size = new_width * new_height * colours; + + uint8_t* scale_buffer = AllocBuffer(scale_buffer_size); + + if ( factor > ZM_SCALE_BASE ) + { + unsigned char *pd = scale_buffer; + unsigned int wc = width*colours; + unsigned int nwc = new_width*colours; + unsigned int h_count = ZM_SCALE_BASE/2; + unsigned int last_h_index = 0; + unsigned int last_w_index = 0; + unsigned int h_index; + for ( int y = 0; y < height; y++ ) + { + unsigned char *ps = &buffer[y*wc]; + unsigned int w_count = ZM_SCALE_BASE/2; + unsigned int w_index; + last_w_index = 0; + for ( int x = 0; x < width; x++ ) + { + w_count += factor; + w_index = w_count/ZM_SCALE_BASE; + for (unsigned int f = last_w_index; f < w_index; f++ ) + { + for ( int c = 0; c < colours; c++ ) + { + *pd++ = *(ps+c); + } + } + ps += colours; + last_w_index = w_index; + } + h_count += factor; + h_index = h_count/ZM_SCALE_BASE; + for ( unsigned int f = last_h_index+1; f < h_index; f++ ) + { + memcpy( pd, pd-nwc, nwc ); + pd += nwc; + } + last_h_index = h_index; + } + new_width = last_w_index; + new_height = last_h_index; + } + else + { + unsigned char *pd = scale_buffer; + unsigned int wc = width*colours; + unsigned int xstart = factor/2; + unsigned int ystart = factor/2; + unsigned int h_count = ystart; + unsigned int last_h_index = 0; + unsigned int last_w_index = 0; + unsigned int h_index; + for ( unsigned int y = 0; y < (unsigned int)height; y++ ) + { + h_count += factor; + h_index = h_count/ZM_SCALE_BASE; + if ( h_index > last_h_index ) + { + unsigned int w_count = xstart; + unsigned int w_index; + last_w_index = 0; + + unsigned char *ps = &buffer[y*wc]; + for ( unsigned int x = 0; x < (unsigned int)width; x++ ) + { + w_count += factor; + w_index = w_count/ZM_SCALE_BASE; + + if ( w_index > last_w_index ) + { + for ( int c = 0; c < colours; c++ ) + { + *pd++ = *ps++; + } + } + else + { + ps += colours; + } + last_w_index = w_index; + } + } + last_h_index = h_index; + } + new_width = last_w_index; + new_height = last_h_index; + } + + AssignDirect( new_width, new_height, colours, subpixelorder, scale_buffer, scale_buffer_size, ZM_BUFTYPE_ZM); + +} + +void Image::Deinterlace_Discard() +{ + /* Simple deinterlacing. Copy the even lines into the odd lines */ + + if ( colours == ZM_COLOUR_GRAY8 ) + { + const uint8_t *psrc; + uint8_t *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = buffer + (y * width); + pdest = buffer + ((y+1) * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + const uint8_t *psrc; + uint8_t *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = buffer + ((y * width) * 3); + pdest = buffer + (((y+1) * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + *pdest++ = *psrc++; + *pdest++ = *psrc++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + const Rgb *psrc; + Rgb *pdest; + for (unsigned int y = 0; y < (unsigned int)height; y += 2) + { + psrc = (Rgb*)(buffer + ((y * width) << 2)); + pdest = (Rgb*)(buffer + (((y+1) * width) << 2)); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pdest++ = *psrc++; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + +} + +void Image::Deinterlace_Linear() +{ + /* Simple deinterlacing. The odd lines are average of the line above and line below */ + + const uint8_t *pbelow, *pabove; + uint8_t *pcurrent; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + ((y-1) * width); + pbelow = buffer + ((y+1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + ((height-1) * width); + pabove = buffer + ((height-2) * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pbelow = buffer + (((y+1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + (((height-1) * width) * 3); + pabove = buffer + (((height-2) * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)(height-1); y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pbelow = buffer + (((y+1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + *pcurrent++ = (*pabove++ + *pbelow++) >> 1; + } + } + /* Special case for the last line */ + pcurrent = buffer + (((height-1) * width) << 2); + pabove = buffer + (((height-2) * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + *pcurrent++ = *pabove++; + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + +} + +void Image::Deinterlace_Blend() +{ + /* Simple deinterlacing. Blend the fields together. 50% blend */ + + uint8_t *pabove, *pcurrent; + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + ((y-1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + *pabove = (*pabove + *pcurrent) >> 1; + *pcurrent++ = *pabove++; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + +} + +void Image::Deinterlace_Blend_CustomRatio(int divider) +{ + /* Simple deinterlacing. Blend the fields together at a custom ratio. */ + /* 1 = 50% blending */ + /* 2 = 25% blending */ + /* 3 = 12.% blending */ + /* 4 = 6.25% blending */ + + uint8_t *pabove, *pcurrent; + uint8_t subpix1, subpix2; + + if ( divider < 1 || divider > 4 ) { + Error("Deinterlace called with invalid blend ratio"); + } + + if ( colours == ZM_COLOUR_GRAY8 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + ((y-1) * width); + pcurrent = buffer + (y * width); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } + else if ( colours == ZM_COLOUR_RGB24 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) * 3); + pcurrent = buffer + ((y * width) * 3); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } + else if ( colours == ZM_COLOUR_RGB32 ) + { + for (unsigned int y = 1; y < (unsigned int)height; y += 2) + { + pabove = buffer + (((y-1) * width) << 2); + pcurrent = buffer + ((y * width) << 2); + for (unsigned int x = 0; x < (unsigned int)width; x++) { + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + subpix1 = ((*pabove - *pcurrent)>>divider) + *pcurrent; + subpix2 = ((*pcurrent - *pabove)>>divider) + *pabove; + *pcurrent++ = subpix1; + *pabove++ = subpix2; + } + } + } else { + Error("Deinterlace called with unexpected colours: %d", colours); + } + +} + + +void Image::Deinterlace_4Field(const Image* next_image, unsigned int threshold) +{ + if ( !(width == next_image->width && height == next_image->height && colours == next_image->colours && subpixelorder == next_image->subpixelorder) ) + { + Panic( "Attempt to deinterlace different sized images, expected %dx%dx%d %d, got %dx%dx%d %d", width, height, colours, subpixelorder, next_image->width, next_image->height, next_image->colours, next_image->subpixelorder); + } + + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + std_deinterlace_4field_bgr(buffer, next_image->buffer, threshold, width, height); + } else { + /* Assume RGB subpixel order */ + std_deinterlace_4field_rgb(buffer, next_image->buffer, threshold, width, height); + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + (*fptr_deinterlace_4field_argb)(buffer, next_image->buffer, threshold, width, height); + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + (*fptr_deinterlace_4field_abgr)(buffer, next_image->buffer, threshold, width, height); + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + (*fptr_deinterlace_4field_bgra)(buffer, next_image->buffer, threshold, width, height); + } else { + /* Assume RGBA subpixel order */ + (*fptr_deinterlace_4field_rgba)(buffer, next_image->buffer, threshold, width, height); + } + break; + } + case ZM_COLOUR_GRAY8: + (*fptr_deinterlace_4field_gray8)(buffer, next_image->buffer, threshold, width, height); + break; + default: + Panic("Deinterlace_4Field called with unexpected colours: %d",colours); + break; + } + +} + + +/************************************************* BLEND FUNCTIONS *************************************************/ + + +__attribute__((noinline,__target__("sse2"))) void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + static uint32_t divider = 0; + static uint32_t clearmask = 0; + static double current_blendpercent = 0.0; + + if(current_blendpercent != blendpercent) { + /* Attempt to match the blending percent to one of the possible values */ + if(blendpercent < 2.34375) { + // 1.5625% blending + divider = 6; + clearmask = 0x03030303; + } else if(blendpercent >= 2.34375 && blendpercent < 4.6875) { + // 3.125% blending + divider = 5; + clearmask = 0x07070707; + } else if(blendpercent >= 4.6875 && blendpercent < 9.375) { + // 6.25% blending + divider = 4; + clearmask = 0x0F0F0F0F; + } else if(blendpercent >= 9.375 && blendpercent < 18.75) { + // 12.5% blending + divider = 3; + clearmask = 0x1F1F1F1F; + } else if(blendpercent >= 18.75 && blendpercent < 37.5) { + // 25% blending + divider = 2; + clearmask = 0x3F3F3F3F; + } else if(blendpercent >= 37.5) { + // 50% blending + divider = 1; + clearmask = 0x7F7F7F7F; + } + current_blendpercent = blendpercent; + } + + __asm__ __volatile__( + "movd %4, %%xmm3\n\t" + "movd %5, %%xmm4\n\t" + "pshufd $0x0, %%xmm3, %%xmm3\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x10, %2\n\t" + "sse2_fastblend_iter:\n\t" + "movdqa (%0,%3),%%xmm0\n\t" + "movdqa %%xmm0,%%xmm2\n\t" + "movdqa (%1,%3),%%xmm1\n\t" + "psrlq %%xmm4,%%xmm0\n\t" + "psrlq %%xmm4,%%xmm1\n\t" + "pand %%xmm3,%%xmm1\n\t" + "pand %%xmm3,%%xmm0\n\t" + "psubb %%xmm0,%%xmm1\n\t" + "paddb %%xmm2,%%xmm1\n\t" + "movntdq %%xmm1,(%2,%3)\n\t" + "sub $0x10, %3\n\t" + "jnz sse2_fastblend_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (clearmask), "m" (divider) + : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +__attribute__((noinline)) void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { + static int divider = 0; + static double current_blendpercent = 0.0; + const uint8_t* const max_ptr = result + count; + + if(current_blendpercent != blendpercent) { + /* Attempt to match the blending percent to one of the possible values */ + if(blendpercent < 2.34375) { + // 1.5625% blending + divider = 6; + } else if(blendpercent >= 2.34375 && blendpercent < 4.6875) { + // 3.125% blending + divider = 5; + } else if(blendpercent >= 4.6875 && blendpercent < 9.375) { + // 6.25% blending + divider = 4; + } else if(blendpercent >= 9.375 && blendpercent < 18.75) { + // 12.5% blending + divider = 3; + } else if(blendpercent >= 18.75 && blendpercent < 37.5) { + // 25% blending + divider = 2; + } else if(blendpercent >= 37.5) { + // 50% blending + divider = 1; + } + current_blendpercent = blendpercent; + } + + + while(result < max_ptr) { + result[0] = ((col2[0] - col1[0])>>divider) + col1[0]; + result[1] = ((col2[1] - col1[1])>>divider) + col1[1]; + result[2] = ((col2[2] - col1[2])>>divider) + col1[2]; + result[3] = ((col2[3] - col1[3])>>divider) + col1[3]; + result[4] = ((col2[4] - col1[4])>>divider) + col1[4]; + result[5] = ((col2[5] - col1[5])>>divider) + col1[5]; + result[6] = ((col2[6] - col1[6])>>divider) + col1[6]; + result[7] = ((col2[7] - col1[7])>>divider) + col1[7]; + result[8] = ((col2[8] - col1[8])>>divider) + col1[8]; + result[9] = ((col2[9] - col1[9])>>divider) + col1[9]; + result[10] = ((col2[10] - col1[10])>>divider) + col1[10]; + result[11] = ((col2[11] - col1[11])>>divider) + col1[11]; + result[12] = ((col2[12] - col1[12])>>divider) + col1[12]; + result[13] = ((col2[13] - col1[13])>>divider) + col1[13]; + result[14] = ((col2[14] - col1[14])>>divider) + col1[14]; + result[15] = ((col2[15] - col1[15])>>divider) + col1[15]; + + col1 += 16; + col2 += 16; + result += 16; + } +} + +__attribute__((noinline)) void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent) { + double divide = blendpercent / 100.0; + double opacity = 1.0 - divide; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + *result++ = (*col1++ * opacity) + (*col2++ * divide); + + } +} + +/************************************************* DELTA FUNCTIONS *************************************************/ + +/* Grayscale */ +__attribute__((noinline)) void std_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 16 bytes (16 grayscale pixels) at a time */ + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + result[0] = abs(col1[0] - col2[0]); + result[1] = abs(col1[1] - col2[1]); + result[2] = abs(col1[2] - col2[2]); + result[3] = abs(col1[3] - col2[3]); + result[4] = abs(col1[4] - col2[4]); + result[5] = abs(col1[5] - col2[5]); + result[6] = abs(col1[6] - col2[6]); + result[7] = abs(col1[7] - col2[7]); + result[8] = abs(col1[8] - col2[8]); + result[9] = abs(col1[9] - col2[9]); + result[10] = abs(col1[10] - col2[10]); + result[11] = abs(col1[11] - col2[11]); + result[12] = abs(col1[12] - col2[12]); + result[13] = abs(col1[13] - col2[13]); + result[14] = abs(col1[14] - col2[14]); + result[15] = abs(col1[15] - col2[15]); + + col1 += 16; + col2 += 16; + result += 16; + } +} + +/* RGB24: RGB */ +__attribute__((noinline)) void std_delta8_rgb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + b = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[3] - col2[3]); + g = abs(col1[4] - col2[4]); + b = abs(col1[5] - col2[5]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[6] - col2[6]); + g = abs(col1[7] - col2[7]); + b = abs(col1[8] - col2[8]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + b = abs(col1[11] - col2[11]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + col2 += 12; + result += 4; + } +} + +/* RGB24: BGR */ +__attribute__((noinline)) void std_delta8_bgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 12 bytes (4 rgb24 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + r = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[3] - col2[3]); + g = abs(col1[4] - col2[4]); + r = abs(col1[5] - col2[5]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[6] - col2[6]); + g = abs(col1[7] - col2[7]); + r = abs(col1[8] - col2[8]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + r = abs(col1[11] - col2[11]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + col2 += 12; + result += 4; + } +} + +/* RGB32: RGBA */ +__attribute__((noinline)) void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + b = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[4] - col2[4]); + g = abs(col1[5] - col2[5]); + b = abs(col1[6] - col2[6]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[8] - col2[8]); + g = abs(col1[9] - col2[9]); + b = abs(col1[10] - col2[10]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[12] - col2[12]); + g = abs(col1[13] - col2[13]); + b = abs(col1[14] - col2[14]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } +} + +/* RGB32: BGRA */ +__attribute__((noinline)) void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[0] - col2[0]); + g = abs(col1[1] - col2[1]); + r = abs(col1[2] - col2[2]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[4] - col2[4]); + g = abs(col1[5] - col2[5]); + r = abs(col1[6] - col2[6]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[8] - col2[8]); + g = abs(col1[9] - col2[9]); + r = abs(col1[10] - col2[10]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[12] - col2[12]); + g = abs(col1[13] - col2[13]); + r = abs(col1[14] - col2[14]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } +} + +/* RGB32: ARGB */ +__attribute__((noinline)) void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = abs(col1[1] - col2[1]); + g = abs(col1[2] - col2[2]); + b = abs(col1[3] - col2[3]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[5] - col2[5]); + g = abs(col1[6] - col2[6]); + b = abs(col1[7] - col2[7]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + b = abs(col1[11] - col2[11]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = abs(col1[13] - col2[13]); + g = abs(col1[14] - col2[14]); + b = abs(col1[15] - col2[15]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } +} + +/* RGB32: ABGR */ +__attribute__((noinline)) void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { + /* Loop unrolling is used to work on 16 bytes (4 rgb32 pixels) at a time */ + int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = abs(col1[1] - col2[1]); + g = abs(col1[2] - col2[2]); + r = abs(col1[3] - col2[3]); + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[5] - col2[5]); + g = abs(col1[6] - col2[6]); + r = abs(col1[7] - col2[7]); + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[9] - col2[9]); + g = abs(col1[10] - col2[10]); + r = abs(col1[11] - col2[11]); + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = abs(col1[13] - col2[13]); + g = abs(col1[14] - col2[14]); + r = abs(col1[15] - col2[15]); + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + col2 += 16; + result += 4; + } +} + +/* Grayscale SSE2 */ +__attribute__((noinline,__target__("sse2"))) void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x10, %2\n\t" + "sse2_delta8_gray8_iter:\n\t" + "movdqa (%0,%3), %%xmm1\n\t" + "movdqa (%1,%3), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm3\n\t" + "movdqa %%xmm2, %%xmm4\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm3, %%xmm4\n\t" + "psubb %%xmm4, %%xmm2\n\t" + "movntdq %%xmm2, (%2,%3)\n\t" + "sub $0x10, %3\n\t" + "jnz sse2_delta8_gray8_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%xmm1", "%xmm2", "%xmm3", "%xmm4", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: RGBA SSE2 */ +__attribute__((noinline,__target__("sse2"))) void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_rgba_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_rgba_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: BGRA SSE2 */ +__attribute__((noinline,__target__("sse2"))) void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_bgra_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_bgra_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: ARGB SSE2 */ +__attribute__((noinline,__target__("sse2"))) void sse2_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_argb_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_argb_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: ABGR SSE2 */ +__attribute__((noinline,__target__("sse2"))) void sse2_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "sse2_delta8_abgr_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" + "movdqa %%xmm2, %%xmm6\n\t" + "pmaxub %%xmm1, %%xmm2\n\t" + "pminub %%xmm5, %%xmm6\n\t" + "psubb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm3\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "packssdw %%xmm1, %%xmm1\n\t" + "packuswb %%xmm1, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz sse2_delta8_abgr_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: RGBA SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_rgba_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_rgba_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: BGRA SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_bgra_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_bgra_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: ARGB SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_argb_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_argb_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* RGB32: ABGR SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %4, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x10, %1\n\t" + "sub $0x4, %2\n\t" + "ssse3_delta8_abgr_iter:\n\t" + "movdqa (%0,%3,4), %%xmm1\n\t" + "movdqa (%1,%3,4), %%xmm2\n\t" + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "psrld $0x8, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x18, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%2,%3)\n\t" + "sub $0x4, %3\n\t" + "jnz ssse3_delta8_abgr_iter\n\t" + : + : "r" (col1), "r" (col2), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + + +/************************************************* CONVERT FUNCTIONS *************************************************/ + +/* RGB24 to grayscale */ +__attribute__((noinline)) void std_convert_rgb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[0]; + g = col1[1]; + b = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[3]; + g = col1[4]; + b = col1[5]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[6]; + g = col1[7]; + b = col1[8]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[9]; + g = col1[10]; + b = col1[11]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + result += 4; + } +} + +/* BGR24 to grayscale */ +__attribute__((noinline)) void std_convert_bgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[0]; + g = col1[1]; + r = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[3]; + g = col1[4]; + r = col1[5]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[6]; + g = col1[7]; + r = col1[8]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[9]; + g = col1[10]; + r = col1[11]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 12; + result += 4; + } +} + +/* RGBA to grayscale */ +__attribute__((noinline)) void std_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[0]; + g = col1[1]; + b = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[4]; + g = col1[5]; + b = col1[6]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[8]; + g = col1[9]; + b = col1[10]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[12]; + g = col1[13]; + b = col1[14]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } +} + +/* BGRA to grayscale */ +__attribute__((noinline)) void std_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[0]; + g = col1[1]; + r = col1[2]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[4]; + g = col1[5]; + r = col1[6]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[8]; + g = col1[9]; + r = col1[10]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[12]; + g = col1[13]; + r = col1[14]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } +} + +/* ARGB to grayscale */ +__attribute__((noinline)) void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + r = col1[1]; + g = col1[2]; + b = col1[3]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + r = col1[5]; + g = col1[6]; + b = col1[7]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + r = col1[9]; + g = col1[10]; + b = col1[11]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + r = col1[13]; + g = col1[14]; + b = col1[15]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } +} + +/* ABGR to grayscale */ +__attribute__((noinline)) void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + b = col1[1]; + g = col1[2]; + r = col1[3]; + result[0] = (r + r + b + g + g + g + g + g)>>3; + b = col1[5]; + g = col1[6]; + r = col1[7]; + result[1] = (r + r + b + g + g + g + g + g)>>3; + b = col1[9]; + g = col1[10]; + r = col1[11]; + result[2] = (r + r + b + g + g + g + g + g)>>3; + b = col1[13]; + g = col1[14]; + r = col1[15]; + result[3] = (r + r + b + g + g + g + g + g)>>3; + + col1 += 16; + result += 4; + } +} + +/* Converts a YUYV image into grayscale by extracting the Y channel */ +__attribute__((noinline)) void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { + const uint16_t* yuvbuf = (const uint16_t*)col1; + const uint8_t* const max_ptr = result + count; + + while(result < max_ptr) { + result[0] = (uint8_t)yuvbuf[0]; + result[1] = (uint8_t)yuvbuf[1]; + result[2] = (uint8_t)yuvbuf[2]; + result[3] = (uint8_t)yuvbuf[3]; + result[4] = (uint8_t)yuvbuf[4]; + result[5] = (uint8_t)yuvbuf[5]; + result[6] = (uint8_t)yuvbuf[6]; + result[7] = (uint8_t)yuvbuf[7]; + result[8] = (uint8_t)yuvbuf[8]; + result[9] = (uint8_t)yuvbuf[9]; + result[10] = (uint8_t)yuvbuf[10]; + result[11] = (uint8_t)yuvbuf[11]; + result[12] = (uint8_t)yuvbuf[12]; + result[13] = (uint8_t)yuvbuf[13]; + result[14] = (uint8_t)yuvbuf[14]; + result[15] = (uint8_t)yuvbuf[15]; + + yuvbuf += 16; + result += 16; + } +} + +/* RGBA to grayscale SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "mov $0xff, %%eax\n\t" + "movd %%eax, %%xmm0\n\t" + "pshufd $0x0, %%xmm0, %%xmm0\n\t" + "movdqa %3, %%xmm5\n\t" + "sub $0x10, %0\n\t" + "sub $0x4, %1\n\t" + "ssse3_convert_rgba_gray8_iter:\n\t" + "movdqa (%0,%2,4), %%xmm3\n\t" + "psrlq $0x3, %%xmm3\n\t" + "pand %%xmm4, %%xmm3\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x8, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "pslld $0x2, %%xmm2\n\t" + "paddd %%xmm1, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm1\n\t" + "pand %%xmm0, %%xmm1\n\t" + "paddd %%xmm1, %%xmm1\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "movdqa %%xmm3, %%xmm2\n\t" + "psrld $0x10, %%xmm2\n\t" + "pand %%xmm0, %%xmm2\n\t" + "paddd %%xmm2, %%xmm1\n\t" + "pshufb %%xmm5, %%xmm1\n\t" + "movd %%xmm1, %%eax\n\t" + "movnti %%eax, (%1,%2)\n\t" + "sub $0x4, %2\n\t" + "jnz ssse3_delta8_abgr_iter\n\t" + : + : "r" (col1), "r" (result), "r" (count), "m" (*movemask) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* Converts a YUYV image into grayscale by extracting the Y channel */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + unsigned long i = 0; + + __attribute__((aligned(16))) static const uint8_t movemask1[16] = {0,2,4,6,8,10,12,14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,2,4,6,8,10,12,14}; + + /* XMM0 - General purpose */ + /* XMM1 - General purpose */ + /* XMM2 - unused */ + /* XMM3 - shift mask 1 */ + /* XMM4 - shift mask 2 */ + /* XMM5 - unused*/ + /* XMM6 - unused */ + /* XMM7 - unused */ + + __asm__ __volatile__ ( + "movdqa %4, %%xmm3\n\t" + "movdqa %5, %%xmm4\n\t" + "algo_ssse3_convert_yuyv_gray8:\n\t" + "movdqa (%0), %%xmm0\n\t" + "pshufb %%xmm3, %%xmm0\n\t" + "movdqa 0x10(%0), %%xmm1\n\t" + "pshufb %%xmm4, %%xmm1\n\t" + "por %%xmm1, %%xmm0\n\t" + "movntdq %%xmm0, (%1)\n\t" + "add $0x10, %3\n\t" + "add $0x10, %1\n\t" + "add $0x20, %0\n\t" + "cmp %2, %3\n\t" + "jb algo_ssse3_convert_yuyv_gray8\n\t" + : +#if (defined(_DEBUG) && !defined(__x86_64__)) /* Use one less register to allow compilation to success on 32bit with omit frame pointer disabled */ + : "r" (col1), "r" (result), "m" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) +#else + : "r" (col1), "r" (result), "r" (count), "r" (i), "m" (*movemask1), "m" (*movemask2) +#endif + : "%xmm3", "%xmm4", "cc", "memory" + ); +#else + Panic("SSE function called on a non x86\\x86-64 platform"); +#endif +} + +/* YUYV to RGB24 - relocated from zm_local_camera.cpp */ +__attribute__((noinline)) void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + unsigned int y1,y2,u,v; + for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 6) { + y1 = col1[0]; + u = col1[1]; + y2 = col1[2]; + v = col1[3]; + + r = y1 + r_v_table[v]; + g = y1 - (g_u_table[u]+g_v_table[v]); + b = y1 + b_u_table[u]; + + result[0] = r<0?0:(r>255?255:r); + result[1] = g<0?0:(g>255?255:g); + result[2] = b<0?0:(b>255?255:b); + + r = y2 + r_v_table[v]; + g = y2 - (g_u_table[u]+g_v_table[v]); + b = y2 + b_u_table[u]; + + result[3] = r<0?0:(r>255?255:r); + result[4] = g<0?0:(g>255?255:g); + result[5] = b<0?0:(b>255?255:b); + } + +} + +/* YUYV to RGBA - modified the one above */ +__attribute__((noinline)) void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + unsigned int y1,y2,u,v; + for(unsigned int i=0; i < count; i += 2, col1 += 4, result += 8) { + y1 = col1[0]; + u = col1[1]; + y2 = col1[2]; + v = col1[3]; + + r = y1 + r_v_table[v]; + g = y1 - (g_u_table[u]+g_v_table[v]); + b = y1 + b_u_table[u]; + + result[0] = r<0?0:(r>255?255:r); + result[1] = g<0?0:(g>255?255:g); + result[2] = b<0?0:(b>255?255:b); + + r = y2 + r_v_table[v]; + g = y2 - (g_u_table[u]+g_v_table[v]); + b = y2 + b_u_table[u]; + + result[4] = r<0?0:(r>255?255:r); + result[5] = g<0?0:(g>255?255:g); + result[6] = b<0?0:(b>255?255:b); + } + +} + +/* RGB555 to RGB24 - relocated from zm_local_camera.cpp */ +__attribute__((noinline)) void zm_convert_rgb555_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; + r = ((*(col1+1))<<1)&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } +} + +/* RGB555 to RGBA - modified the one above */ +__attribute__((noinline)) void zm_convert_rgb555_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<6)|((*col1)>>2))&0xf8; + r = ((*(col1+1))<<1)&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } +} + +/* RGB565 to RGB24 - relocated from zm_local_camera.cpp */ +__attribute__((noinline)) void zm_convert_rgb565_rgb(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 3) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; + r = (*(col1+1))&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } +} + +/* RGB565 to RGBA - modified the one above */ +__attribute__((noinline)) void zm_convert_rgb565_rgba(const uint8_t* col1, uint8_t* result, unsigned long count) { + unsigned int r,g,b; + for(unsigned int i=0; i < count; i++, col1 += 2, result += 4) { + b = ((*col1)<<3)&0xf8; + g = (((*(col1+1))<<5)|((*col1)>>3))&0xfc; + r = (*(col1+1))&0xf8; + result[0] = r; + result[1] = g; + result[2] = b; + } +} + +/************************************************* DEINTERLACE FUNCTIONS *************************************************/ + +/* Grayscale */ +__attribute__((noinline)) void std_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const uint8_t* const max_ptr = col1 + (width*(height-1)); + const uint8_t *max_ptr2; + + pcurrent = col1 + width; + pncurrent = col2 + width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + width; + while(pcurrent < max_ptr2) { + if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { + *pcurrent = (*pabove + *pbelow) >> 1; + } + pabove++; + pnabove++; + pcurrent++; + pncurrent++; + pbelow++; + } + pcurrent += width; + pncurrent += width; + pabove += width; + pnabove += width; + pbelow += width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + width; + while(pcurrent < max_ptr2) { + if((unsigned int)((abs(*pnabove - *pabove) + abs(*pncurrent - *pcurrent)) >> 1) >= threshold) { + *pcurrent = *pabove; + } + pabove++; + pnabove++; + pcurrent++; + pncurrent++; + } +} + +/* RGB */ +__attribute__((noinline)) void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*3; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + (width*3); + pncurrent = col2 + (width*3); + pabove = col1; + pnabove = col2; + pbelow = col1 + ((width*2)*3); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + pbelow += 3; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + } +} + +/* BGR */ +__attribute__((noinline)) void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*3; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + (width*3); + pncurrent = col2 + (width*3); + pabove = col1; + pnabove = col2; + pbelow = col1 + ((width*2)*3); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + pbelow += 3; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 3; + pnabove += 3; + pcurrent += 3; + pncurrent += 3; + } +} + +/* RGBA */ +__attribute__((noinline)) void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + b = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + b = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } +} + +/* BGRA */ +__attribute__((noinline)) void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = (pabove[0] + pbelow[0]) >> 1; + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[0] - pabove[0]); + g = abs(pnabove[1] - pabove[1]); + r = abs(pnabove[2] - pabove[2]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[0] - pcurrent[0]); + g = abs(pncurrent[1] - pcurrent[1]); + r = abs(pncurrent[2] - pcurrent[2]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[0] = pabove[0]; + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } +} + +/* ARGB */ +__attribute__((noinline)) void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + b = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + b = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + r = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + b = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + r = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + b = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + pcurrent[3] = pabove[3]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } +} + +/* ABGR */ +__attribute__((noinline)) void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) +{ + uint8_t *pcurrent, *pabove, *pncurrent, *pnabove, *pbelow; + const unsigned int row_width = width*4; + const uint8_t* const max_ptr = col1 + (row_width * (height-1)); + const uint8_t *max_ptr2; + unsigned int b, g, r; + unsigned int delta1, delta2; + + pcurrent = col1 + row_width; + pncurrent = col2 + row_width; + pabove = col1; + pnabove = col2; + pbelow = col1 + (row_width*2); + while(pcurrent < max_ptr) + { + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + r = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + r = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = (pabove[1] + pbelow[1]) >> 1; + pcurrent[2] = (pabove[2] + pbelow[2]) >> 1; + pcurrent[3] = (pabove[3] + pbelow[3]) >> 1; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + pbelow += 4; + } + pcurrent += row_width; + pncurrent += row_width; + pabove += row_width; + pnabove += row_width; + pbelow += row_width; + + } + + /* Special case for the last line */ + max_ptr2 = pcurrent + row_width; + while(pcurrent < max_ptr2) { + b = abs(pnabove[1] - pabove[1]); + g = abs(pnabove[2] - pabove[2]); + r = abs(pnabove[3] - pabove[3]); + delta1 = (r + r + b + g + g + g + g + g)>>3; + b = abs(pncurrent[1] - pcurrent[1]); + g = abs(pncurrent[2] - pcurrent[2]); + r = abs(pncurrent[3] - pcurrent[3]); + delta2 = (r + r + b + g + g + g + g + g)>>3; + if(((delta1 + delta2) >> 1) >= threshold) { + pcurrent[1] = pabove[1]; + pcurrent[2] = pabove[2]; + pcurrent[3] = pabove[3]; + } + pabove += 4; + pnabove += 4; + pcurrent += 4; + pncurrent += 4; + } +} + +/* Grayscale SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { + + union { + uint32_t int32; + uint8_t int8a[4]; + } threshold_mask; + threshold_mask.int8a[0] = threshold; + threshold_mask.int8a[1] = 0; + threshold_mask.int8a[2] = threshold; + threshold_mask.int8a[3] = 0; + + unsigned long row_width = width; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; + + __asm__ __volatile__ ( + /* Load the threshold */ + "mov %5, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" + + "algo_ssse3_deinterlace_4field_gray8:\n\t" + + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm5, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "pmaxub %%xmm2, %%xmm1\n\t" + "pminub %%xmm6, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + "movdqa %%xmm1, %%xmm2\n\t" + + /* Do the comparison on words instead of bytes because we don't have unsigned comparison */ + "punpcklbw %%xmm0, %%xmm1\n\t" // Expand pixels 0-7 into words into xmm1 + "punpckhbw %%xmm0, %%xmm2\n\t" // Expand pixels 8-15 into words into xmm2 + "pcmpgtw %%xmm4, %%xmm1\n\t" // Compare average delta with threshold for pixels 0-7 + "pcmpgtw %%xmm4, %%xmm2\n\t" // Compare average delta with threshold for pixels 8-15 + "packsswb %%xmm2, %%xmm1\n\t" // Pack the comparison results into xmm1 + + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove + + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent + + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration + + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 + + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_gray8\n\t" // Go for another iteration + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_mask.int32) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + ); +} + +/* RGBA SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,0,0,2,9,9,9,9,9,8,8,10}; + + const uint32_t threshold_val = threshold; + + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" +#if defined(__x86_64__) + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" +#endif + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" + + "algo_ssse3_deinterlace_4field_rgba:\n\t" + + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove + + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent + + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration + + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 + + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_rgba\n\t" // Go for another iteration + + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) +#if defined(__x86_64__) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" +#else + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" +#endif + ); +} + +/* BGRA SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {1,1,1,1,1,2,2,0,9,9,9,9,9,10,10,8}; + + const uint32_t threshold_val = threshold; + + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" +#if defined(__x86_64__) + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" +#endif + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" + + "algo_ssse3_deinterlace_4field_bgra:\n\t" + + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove + + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent + + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration + + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 + + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_bgra\n\t" // Go for another iteration + + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) +#if defined(__x86_64__) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" +#else + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" +#endif + ); +} + +/* ARGB SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,1,1,3,10,10,10,10,10,9,9,11}; + + const uint32_t threshold_val = threshold; + + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" +#if defined(__x86_64__) + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" +#endif + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" + + "algo_ssse3_deinterlace_4field_argb:\n\t" + + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove + + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent + + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration + + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 + + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_argb\n\t" // Go for another iteration + + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) +#if defined(__x86_64__) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" +#else + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" +#endif + ); +} + +/* ABGR SSSE3 */ +__attribute__((noinline,__target__("ssse3"))) void ssse3_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height) { + __attribute__((aligned(16))) static const uint8_t movemask2[16] = {2,2,2,2,2,3,3,1,10,10,10,10,10,11,11,9}; + + const uint32_t threshold_val = threshold; + + unsigned long row_width = width*4; + uint8_t* max_ptr = col1 + (row_width * (height-2)); + uint8_t* max_ptr2 = col1 + row_width; + + __asm__ __volatile__ ( + "mov $0x1F1F1F1F, %%eax\n\t" + "movd %%eax, %%xmm4\n\t" + "pshufd $0x0, %%xmm4, %%xmm4\n\t" + "movdqa %6, %%xmm3\n\t" + "mov %5, %%eax\n\t" +#if defined(__x86_64__) + "movd %%eax, %%xmm8\n\t" + "pshufd $0x0, %%xmm8, %%xmm8\n\t" +#endif + /* Zero the temporary register */ + "pxor %%xmm0, %%xmm0\n\t" + + "algo_ssse3_deinterlace_4field_abgr:\n\t" + + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "movdqa (%0,%4), %%xmm2\n\t" // Load pbelow + "pavgb %%xmm5, %%xmm2\n\t" // Average pabove and pbelow + "pand %%xmm1, %%xmm2\n\t" // Filter out pixels in avg that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm2, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + + "sub %4, %0\n\t" // Restore pcurrent to pabove + "sub %4, %1\n\t" // Restore pncurrent to pnabove + + /* Next pixels */ + "add $0x10, %0\n\t" // Add 16 to pcurrent + "add $0x10, %1\n\t" // Add 16 to pncurrent + + /* Check if we reached the row end */ + "cmp %2, %0\n\t" + "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration + + /* Next row */ + "add %4, %0\n\t" // Add width to pcurrent + "add %4, %1\n\t" // Add width to pncurrent + "mov %0, %2\n\t" + "add %4, %2\n\t" // Add width to max_ptr2 + + /* Check if we reached the end */ + "cmp %3, %0\n\t" + "jb algo_ssse3_deinterlace_4field_abgr\n\t" // Go for another iteration + + /* Special case for the last line */ + /* Load pabove into xmm1 and pnabove into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm5\n\t" /* Keep backup of pabove in xmm5 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + "movdqa %%xmm1, %%xmm7\n\t" /* Backup of delta2 in xmm7 for now */ + + /* Next row */ + "add %4, %0\n\t" + "add %4, %1\n\t" + + /* Load pcurrent into xmm1 and pncurrent into xmm2 */ + "movdqa (%0), %%xmm1\n\t" + "movdqa (%1), %%xmm2\n\t" + "movdqa %%xmm1, %%xmm6\n\t" /* Keep backup of pcurrent in xmm6 */ + "psrlq $0x3, %%xmm1\n\t" + "psrlq $0x3, %%xmm2\n\t" + "pand %%xmm4, %%xmm1\n\t" + "pand %%xmm4, %%xmm2\n\t" + "psubb %%xmm2, %%xmm1\n\t" + "pabsb %%xmm1, %%xmm2\n\t" + "movdqa %%xmm2, %%xmm1\n\t" + "punpckldq %%xmm1, %%xmm1\n\t" + "pshufb %%xmm3, %%xmm1\n\t" + "psadbw %%xmm0, %%xmm1\n\t" + "punpckhdq %%xmm2, %%xmm2\n\t" + "pshufb %%xmm3, %%xmm2\n\t" + "psadbw %%xmm0, %%xmm2\n\t" + "packuswb %%xmm2, %%xmm1\n\t" + + "pavgb %%xmm7, %%xmm1\n\t" // Average the two deltas together + +#if defined(__x86_64__) + "pcmpgtd %%xmm8, %%xmm1\n\t" // Compare average delta with the threshold +#else + "movd %%eax, %%xmm7\n\t" // Setup the threshold + "pshufd $0x0, %%xmm7, %%xmm7\n\t" + + "pcmpgtd %%xmm7, %%xmm1\n\t" // Compare average delta with the threshold +#endif + "pand %%xmm1, %%xmm5\n\t" // Filter out pixels in pabove that shouldn't be copied + "pandn %%xmm6, %%xmm1\n\t" // Filter out pixels in pcurrent that should be replaced + + "por %%xmm5, %%xmm1\n\t" // Put the new values in pcurrent + "movntdq %%xmm1, (%0)\n\t" // Write pcurrent + : + : "r" (col1), "r" (col2), "r" (max_ptr2), "r" (max_ptr), "r" (row_width), "m" (threshold_val), "m" (*movemask2) +#if defined(__x86_64__) + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "%xmm8", "cc", "memory" +#else + : "%eax", "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" +#endif + ); +} + diff --git a/src/zm_image.h b/src/zm_image.h new file mode 100644 index 000000000..c6ffd2a54 --- /dev/null +++ b/src/zm_image.h @@ -0,0 +1,308 @@ +// +// ZoneMinder Image Class Interface, $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. +// + +#ifndef ZM_IMAGE_H +#define ZM_IMAGE_H + +#include "zm.h" +extern "C" +{ +#include "zm_jpeg.h" +} +#include "zm_rgb.h" +#include "zm_coord.h" +#include "zm_box.h" +#include "zm_poly.h" +#include "zm_mem_utils.h" +#include "zm_utils.h" + +#include + +#if HAVE_ZLIB_H +#include +#endif // HAVE_ZLIB_H + +#define ZM_BUFTYPE_DONTFREE 0 +#define ZM_BUFTYPE_MALLOC 1 +#define ZM_BUFTYPE_NEW 2 +#define ZM_BUFTYPE_AVMALLOC 3 +#define ZM_BUFTYPE_ZM 4 + +typedef void (*blend_fptr_t)(const uint8_t*, const uint8_t*, uint8_t*, unsigned long, double); +typedef void (*delta_fptr_t)(const uint8_t*, const uint8_t*, uint8_t*, unsigned long); +typedef void (*convert_fptr_t)(const uint8_t*, uint8_t*, unsigned long); +typedef void (*deinterlace_4field_fptr_t)(uint8_t*, uint8_t*, unsigned int, unsigned int, unsigned int); +typedef void* (*imgbufcpy_fptr_t)(void*, const void*, size_t); + +extern imgbufcpy_fptr_t fptr_imgbufcpy; + +/* Should be called from Image class functions */ +inline static uint8_t* AllocBuffer(size_t p_bufsize) { + uint8_t* buffer = (uint8_t*)zm_mallocaligned(16,p_bufsize); + if(buffer == NULL) + Fatal("Memory allocation failed: %s",strerror(errno)); + + return buffer; +} + +inline static void DumpBuffer(uint8_t* buffer, int buffertype) { + if (buffer && buffertype != ZM_BUFTYPE_DONTFREE) { + if(buffertype == ZM_BUFTYPE_ZM) + zm_freealigned(buffer); + else if(buffertype == ZM_BUFTYPE_MALLOC) + free(buffer); + else if(buffertype == ZM_BUFTYPE_NEW) + delete buffer; + /*else if(buffertype == ZM_BUFTYPE_AVMALLOC) + av_free(buffer); + */ + } +} + + +// +// This is image class, and represents a frame captured from a +// camera in raw form. +// +class Image +{ +protected: + + struct Edge + { + int min_y; + int max_y; + double min_x; + double _1_m; + + static int CompareYX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + if ( e1->min_y == e2->min_y ) + return( int(e1->min_x - e2->min_x) ); + else + return( int(e1->min_y - e2->min_y) ); + } + static int CompareX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + return( int(e1->min_x - e2->min_x) ); + } + }; + + inline void DumpImgBuffer() { + DumpBuffer(buffer,buffertype); + buffer = NULL; + allocation = 0; + } + + inline void AllocImgBuffer(size_t p_bufsize) { + if(buffer) + DumpImgBuffer(); + + buffer = AllocBuffer(p_bufsize); + buffertype = ZM_BUFTYPE_ZM; + allocation = p_bufsize; + } + +public: + enum { CHAR_HEIGHT=11, CHAR_WIDTH=6 }; + enum { LINE_HEIGHT=CHAR_HEIGHT+0 }; + +protected: + static bool initialised; + static unsigned char *abs_table; + static unsigned char *y_r_table; + static unsigned char *y_g_table; + static unsigned char *y_b_table; + static jpeg_compress_struct *jpg_ccinfo[101]; + static jpeg_decompress_struct *jpg_dcinfo; + static struct zm_error_mgr jpg_err; + +protected: + int width; + int height; + int pixels; + int colours; + int size; + int subpixelorder; + unsigned long allocation; + uint8_t *buffer; + int buffertype; /* 0=not ours, no need to call free(), 1=malloc() buffer, 2=new buffer */ + int holdbuffer; /* Hold the buffer instead of replacing it with new one */ + char text[1024]; + +protected: + static void Initialise(); + +public: + Image(); + Image( const char *filename ); + Image( int p_width, int p_height, int p_colours, int p_subpixelorder, uint8_t *p_buffer=0); + Image( const Image &p_image ); + ~Image(); + + inline int Width() const { return( width ); } + inline int Height() const { return( height ); } + inline int Pixels() const { return( pixels ); } + inline int Colours() const { return( colours ); } + inline int SubpixelOrder() const { return( subpixelorder ); } + inline int Size() const { return( size ); } + + /* Internal buffer should not be modified from functions outside of this class */ + inline const uint8_t* Buffer() const { return( buffer ); } + inline const uint8_t* Buffer( unsigned int x, unsigned int y= 0 ) const { return( &buffer[colours*((y*width)+x)] ); } + /* Request writeable buffer */ + uint8_t* WriteBuffer(const int p_width, const int p_height, const int p_colours, const int p_subpixelorder); + + inline int IsBufferHeld() const { return holdbuffer; } + inline void HoldBuffer(int tohold) { holdbuffer = tohold; } + + inline void Empty() { + if(!holdbuffer) + DumpImgBuffer(); + + width = height = colours = size = pixels = subpixelorder = 0; + } + + void Assign( int p_width, int p_height, int p_colours, int p_subpixelorder, const uint8_t* new_buffer, const size_t buffer_size); + void Assign( const Image &image ); + void AssignDirect( const int p_width, const int p_height, const int p_colours, const int p_subpixelorder, uint8_t *new_buffer, const size_t buffer_size, const int p_buffertype); + + inline void CopyBuffer( const Image &image ) + { + if ( image.size != size ) + { + Panic( "Attempt to copy different size image buffers, expected %d, got %d", size, image.size ); + } + (*fptr_imgbufcpy)(buffer, image.buffer, size); + } + inline Image &operator=( const unsigned char *new_buffer ) + { + (*fptr_imgbufcpy)(buffer, new_buffer, size); + return( *this ); + } + + bool ReadRaw( const char *filename ); + bool WriteRaw( const char *filename ) const; + + bool ReadJpeg( const char *filename, int p_colours, int p_subpixelorder); + bool WriteJpeg( const char *filename, int quality_override=0 ) const; + bool DecodeJpeg( const JOCTET *inbuffer, int inbuffer_size, int p_colours, int p_subpixelorder); + bool EncodeJpeg( JOCTET *outbuffer, int *outbuffer_size, int quality_override=0 ) const; + +#if HAVE_ZLIB_H + bool Unzip( const Bytef *inbuffer, unsigned long inbuffer_size ); + bool Zip( Bytef *outbuffer, unsigned long *outbuffer_size, int compression_level=Z_BEST_SPEED ) const; +#endif // HAVE_ZLIB_H + + bool Crop( int lo_x, int lo_y, int hi_x, int hi_y ); + bool Crop( const Box &limits ); + + void Overlay( const Image &image ); + void Overlay( const Image &image, int x, int y ); + void Blend( const Image &image, int transparency=12 ); + static Image *Merge( int n_images, Image *images[] ); + static Image *Merge( int n_images, Image *images[], double weight ); + static Image *Highlight( int n_images, Image *images[], const Rgb threshold=RGB_BLACK, const Rgb ref_colour=RGB_RED ); + //Image *Delta( const Image &image ) const; + void Delta( const Image &image, Image* targetimage) const; + + const Coord centreCoord( const char *text ) const; + void Annotate( const char *p_text, const Coord &coord, const Rgb fg_colour=RGB_WHITE, const Rgb bg_colour=RGB_BLACK ); + Image *HighlightEdges( Rgb colour, int p_colours, int p_subpixelorder, const Box *limits=0 ); + //Image *HighlightEdges( Rgb colour, const Polygon &polygon ); + void Timestamp( const char *label, const time_t when, const Coord &coord ); + void Colourise(const int p_reqcolours, const int p_reqsubpixelorder); + void DeColourise(); + + void Clear() { memset( buffer, 0, size ); } + void Fill( Rgb colour, const Box *limits=0 ); + void Fill( Rgb colour, int density, const Box *limits=0 ); + void Outline( Rgb colour, const Polygon &polygon ); + void Fill( Rgb colour, const Polygon &polygon ); + void Fill( Rgb colour, int density, const Polygon &polygon ); + + void Rotate( int angle ); + void Flip( bool leftright ); + void Scale( unsigned int factor ); + + void Deinterlace_Discard(); + void Deinterlace_Linear(); + void Deinterlace_Blend(); + void Deinterlace_Blend_CustomRatio(int divider); + void Deinterlace_4Field(const Image* next_image, unsigned int threshold); + +}; + +#endif // ZM_IMAGE_H + +/* Blend functions */ +void sse2_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent); +void std_fastblend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent); +void std_blend(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count, double blendpercent); + +/* Delta functions */ +void std_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_rgb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_bgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void std_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void sse2_delta8_gray8(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void sse2_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void sse2_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void sse2_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void sse2_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void ssse3_delta8_rgba(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void ssse3_delta8_bgra(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void ssse3_delta8_argb(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); +void ssse3_delta8_abgr(const uint8_t* col1, const uint8_t* col2, uint8_t* result, unsigned long count); + +/* Convert functions */ +void std_convert_rgb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_bgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_bgra_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_argb_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_abgr_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void std_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void ssse3_convert_rgba_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void ssse3_convert_yuyv_gray8(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_yuyv_rgb(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_yuyv_rgba(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_rgb555_rgb(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_rgb555_rgba(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_rgb565_rgb(const uint8_t* col1, uint8_t* result, unsigned long count); +void zm_convert_rgb565_rgba(const uint8_t* col1, uint8_t* result, unsigned long count); + +/* Deinterlace_4Field functions */ +void std_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_rgb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_bgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void std_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void ssse3_deinterlace_4field_gray8(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void ssse3_deinterlace_4field_rgba(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void ssse3_deinterlace_4field_bgra(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void ssse3_deinterlace_4field_argb(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); +void ssse3_deinterlace_4field_abgr(uint8_t* col1, uint8_t* col2, unsigned int threshold, unsigned int width, unsigned int height); diff --git a/src/zm_image_analyser.cpp b/src/zm_image_analyser.cpp new file mode 100644 index 000000000..ee598a5a6 --- /dev/null +++ b/src/zm_image_analyser.cpp @@ -0,0 +1,87 @@ +#include "zm_image_analyser.h" + + + +/*!\fn ImageAnalyser::ImageAnalyser(const ImageAnalyser& source) + * \param source is the object to copy + */ +ImageAnalyser::ImageAnalyser(const ImageAnalyser& source) +{ + m_Detectors = source.m_Detectors; +} + + + +/*!\fn ImageAnalyser::operator=(const ImageAnalyser& source) + * \param source is the object to copy + */ +ImageAnalyser& ImageAnalyser::operator=(const ImageAnalyser& source) +{ + m_Detectors = source.m_Detectors; + return *this; +} + + + +ImageAnalyser::~ImageAnalyser() +{ + for(DetectorsList::reverse_iterator It = m_Detectors.rbegin(); + It != m_Detectors.rend(); + ++It) + delete *It; +} + + + +/*!\fn ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause) + * \param comp_image is the image to analyse + * \param zones is the zones array to analyse + * \param n_numZones is the number of zones + * \param noteSetMap is the map of events descriptions + * \param det_cause is a string describing detection cause + */ +int ImageAnalyser::DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause) +{ + Event::StringSet zoneSet; + int score = 0; + + for(DetectorsList::iterator It = m_Detectors.begin(); + It != m_Detectors.end(); + ++It) + { + int detect_score = (*It)->Detect(comp_image, zones, n_numZones, zoneSet); + if (detect_score) + { + score += detect_score; + noteSetMap[(*It)->getDetectionCause()] = zoneSet; + if (det_cause.length()) + det_cause += ", "; + det_cause += (*It)->getDetectionCause(); + } + } + return score; +} + + + +/*!\fn ImageAnalyser::configurePlugins(string sConfigFileName) + * \param sConfigFileName is the path to the configuration file, where parameters for all plugins are given. + */ +void ImageAnalyser::configurePlugins(string sConfigFileName) +{ + for(DetectorsList::iterator It = m_Detectors.begin(); + It != m_Detectors.end(); + ++It) + { + try + { + (*It)->loadConfig(sConfigFileName); + } + catch(...) + { + //Info("ERROR: Plugin \"%s\" couldn\'t load config file \"%s\".", (*It)->getDetectionCause().c_str(), sConfigFileName.c_str()); + Info("ERROR: Plugin couldn\'t load config file ."); + } + } + +} diff --git a/src/zm_image_analyser.h b/src/zm_image_analyser.h new file mode 100644 index 000000000..644e97fbf --- /dev/null +++ b/src/zm_image_analyser.h @@ -0,0 +1,65 @@ +#ifndef ZM_IMAGE_ANALYSER_H +#define ZM_IMAGE_ANALYSER_H + + + +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_detector.h" +#include "zm_image.h" +#include "zm_zone.h" +#include "zm_event.h" + + + +using namespace std; + + +//! List of available detectors. +typedef std::list DetectorsList; + + +//! Class for handling image detection. +/*! Contains all detectors loaded from plugins. + */ +class ImageAnalyser { + public: + + //!Default constructor. + ImageAnalyser() {}; + + //! Destructor. + ~ImageAnalyser(); + + //! Copy constructor. + ImageAnalyser(const ImageAnalyser& source); + + //! Overloaded operator=. + ImageAnalyser& operator=(const ImageAnalyser& source); + + //! Adds new plugin's detector to the list of detectors. + void addDetector(std::auto_ptr Det) + { + m_Detectors.push_back(Det.release()); + } + + //! Do detection in an image by calling all available detectors. + int DoDetection(const Image &comp_image, Zone** zones, int n_numZones, Event::StringSetMap noteSetMap, std::string& det_cause); + + //! Configure all loaded plugins using given configuration file. + void configurePlugins(string sConfigFileName); + +private: + + //! All available detectors. + DetectorsList m_Detectors; +}; + + + +#endif //ZM_IMAGE_ANALYSER_H diff --git a/src/zm_jpeg.cpp b/src/zm_jpeg.cpp new file mode 100644 index 000000000..58c3ca5be --- /dev/null +++ b/src/zm_jpeg.cpp @@ -0,0 +1,466 @@ +/* + * ZoneMinder JPEG memory encoding/decoding, $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. +*/ + +#include "zm_jpeg.h" +#include "zm_logger.h" + +#include + +/* Overridden error handlers, mostly for decompression */ +extern "C" +{ + +#define MAX_JPEG_ERRS 25 + +static int jpeg_err_count = 0; + +void zm_jpeg_error_exit( j_common_ptr cinfo ) +{ + static char buffer[JMSG_LENGTH_MAX]; + zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; + + (zmerr->pub.format_message)( cinfo, buffer ); + + Error( "%s", buffer ); + if ( ++jpeg_err_count == MAX_JPEG_ERRS ) + { + Fatal( "Maximum number (%d) of JPEG errors reached, exiting", jpeg_err_count ); + } + + longjmp( zmerr->setjmp_buffer, 1 ); +} + +void zm_jpeg_emit_message( j_common_ptr cinfo, int msg_level ) +{ + static char buffer[JMSG_LENGTH_MAX]; + zm_error_ptr zmerr = (zm_error_ptr)cinfo->err; + + if ( msg_level < 0 ) + { + /* It's a warning message. Since corrupt files may generate many warnings, + * the policy implemented here is to show only the first warning, + * unless trace_level >= 3. + */ + if ( zmerr->pub.num_warnings == 0 || zmerr->pub.trace_level >= 3 ) + { + (zmerr->pub.format_message)( cinfo, buffer ); + Warning( "%s", buffer ); + } + /* Always count warnings in num_warnings. */ + zmerr->pub.num_warnings++; + } + else + { + /* It's a trace message. Show it if trace_level >= msg_level. */ + if ( zmerr->pub.trace_level >= msg_level ) + { + (zmerr->pub.format_message)( cinfo, buffer ); + Debug( msg_level, "%s", buffer ); + } + } +} + +/* Expanded data destination object for memory */ + +typedef struct +{ + struct jpeg_destination_mgr pub; /* public fields */ + + JOCTET *outbuffer; /* target buffer */ + int *outbuffer_size; + JOCTET *buffer; /* start of buffer */ +} mem_destination_mgr; + +typedef mem_destination_mgr * mem_dest_ptr; + +#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */ + +/* + * Initialize destination --- called by jpeg_start_compress + * before any data is actually written. + */ + +static void init_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + /* Allocate the output buffer --- it will be released when done with image */ + dest->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + *(dest->outbuffer_size) = 0; +} + + +/* + * Empty the output buffer --- called whenever buffer fills up. + * + * In typical applications, this should write the entire output buffer + * (ignoring the current state of next_output_byte & free_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been dumped. + * + * In applications that need to be able to suspend compression due to output + * overrun, a FALSE return indicates that the buffer cannot be emptied now. + * In this situation, the compressor will return to its caller (possibly with + * an indication that it has not accepted all the supplied scanlines). The + * application should resume compression after it has made more room in the + * output buffer. Note that there are substantial restrictions on the use of + * suspension --- see the documentation. + * + * When suspending, the compressor will back up to a convenient restart point + * (typically the start of the current MCU). next_output_byte & free_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point will be regenerated after resumption, so do not + * write it out when emptying the buffer externally. + */ + +static boolean empty_output_buffer (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, OUTPUT_BUF_SIZE ); + *(dest->outbuffer_size) += OUTPUT_BUF_SIZE; + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; + + return( TRUE ); +} + +/* + * Terminate destination --- called by jpeg_finish_compress + * after all data has been written. Usually needs to flush buffer. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +static void term_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; + + if ( datacount > 0 ) + { + memcpy( dest->outbuffer+*(dest->outbuffer_size), dest->buffer, datacount ); + *(dest->outbuffer_size) += datacount; + } +} + + +/* + * Prepare for output to a stdio stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing compression. + */ + +void zm_jpeg_mem_dest (j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size ) +{ + mem_dest_ptr dest; + + /* The destination object is made permanent so that multiple JPEG images + * can be written to the same file without re-executing jpeg_stdio_dest. + * This makes it dangerous to use this manager and a different destination + * manager serially with the same JPEG object, because their private object + * sizes may be different. Caveat programmer. + */ + if ( cinfo->dest == NULL ) + { + /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_destination_mgr)); + } + + dest = (mem_dest_ptr) cinfo->dest; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; + dest->outbuffer = outbuffer; + dest->outbuffer_size = outbuffer_size; +} + +/* Expanded data source object for memory input */ + +typedef struct +{ + struct jpeg_source_mgr pub; /* public fields */ + + JOCTET * inbuffer; /* source stream */ + int inbuffer_size; + int inbuffer_size_hwm; /* High water mark */ + + JOCTET * buffer; /* start of buffer */ + boolean start_of_data; /* have we gotten any data yet? */ +} mem_source_mgr; + +typedef mem_source_mgr * mem_src_ptr; + +#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */ + +/* + * Initialize source --- called by jpeg_read_header + * before any data is actually read. + */ + +static void init_source (j_decompress_ptr cinfo) +{ + mem_src_ptr src = (mem_src_ptr) cinfo->src; + + /* We reset the empty-input-file flag for each image, + * but we don't clear the input buffer. + * This is correct behavior for reading a series of images from one source. + */ + src->start_of_data = TRUE; + src->pub.bytes_in_buffer = 0; +} + + +/* + * Fill the input buffer --- called whenever buffer is emptied. + * + * In typical applications, this should read fresh data into the buffer + * (ignoring the current state of next_input_byte & bytes_in_buffer), + * reset the pointer & count to the start of the buffer, and return TRUE + * indicating that the buffer has been reloaded. It is not necessary to + * fill the buffer entirely, only to obtain at least one more byte. + * + * There is no such thing as an EOF return. If the end of the file has been + * reached, the routine has a choice of ERREXIT() or inserting fake data into + * the buffer. In most cases, generating a warning message and inserting a + * fake EOI marker is the best course of action --- this will allow the + * decompressor to output however much of the image is there. However, + * the resulting error message is misleading if the real problem is an empty + * input file, so we handle that case specially. + * + * In applications that need to be able to suspend compression due to input + * not being available yet, a FALSE return indicates that no more data can be + * obtained right now, but more may be forthcoming later. In this situation, + * the decompressor will return to its caller (with an indication of the + * number of scanlines it has read, if any). The application should resume + * decompression after it has loaded more data into the input buffer. Note + * that there are substantial restrictions on the use of suspension --- see + * the documentation. + * + * When suspending, the decompressor will back up to a convenient restart point + * (typically the start of the current MCU). next_input_byte & bytes_in_buffer + * indicate where the restart point will be if the current call returns FALSE. + * Data beyond this point must be rescanned after resumption, so move it to + * the front of the buffer rather than discarding it. + */ + +static boolean fill_input_buffer (j_decompress_ptr cinfo) +{ + mem_src_ptr src = (mem_src_ptr) cinfo->src; + size_t nbytes; + + memcpy( src->buffer, src->inbuffer, (size_t) src->inbuffer_size ); + nbytes = src->inbuffer_size; + + if ( nbytes <= 0 ) + { + if ( src->start_of_data ) /* Treat empty input file as fatal error */ + ERREXIT(cinfo, JERR_INPUT_EMPTY); + WARNMS(cinfo, JWRN_JPEG_EOF); + /* Insert a fake EOI marker */ + src->buffer[0] = (JOCTET) 0xFF; + src->buffer[1] = (JOCTET) JPEG_EOI; + nbytes = 2; + } + + src->pub.next_input_byte = src->buffer; + src->pub.bytes_in_buffer = nbytes; + src->start_of_data = FALSE; + + return( TRUE ); +} + + +/* + * Skip data --- used to skip over a potentially large amount of + * uninteresting data (such as an APPn marker). + * + * Writers of suspendable-input applications must note that skip_input_data + * is not granted the right to give a suspension return. If the skip extends + * beyond the data currently in the buffer, the buffer can be marked empty so + * that the next read will cause a fill_input_buffer call that can suspend. + * Arranging for additional bytes to be discarded before reloading the input + * buffer is the application writer's problem. + */ + +static void skip_input_data (j_decompress_ptr cinfo, long num_bytes) +{ + mem_src_ptr src = (mem_src_ptr) cinfo->src; + + /* Just a dumb implementation for now. Could use fseek() except + * it doesn't work on pipes. Not clear that being smart is worth + * any trouble anyway --- large skips are infrequent. + */ + if ( num_bytes > 0 ) + { + while ( num_bytes > (long) src->pub.bytes_in_buffer ) + { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + /* note we assume that fill_input_buffer will never return FALSE, + * so suspension need not be handled. + */ + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } +} + + +/* + * Terminate source --- called by jpeg_finish_decompress + * after all data has been read. Often a no-op. + * + * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding + * application must deal with any cleanup that should happen even + * for error exit. + */ + +static void term_source (j_decompress_ptr cinfo) +{ + /* no work necessary here */ +} + + +/* + * Prepare for input from a memory stream. + * The caller must have already opened the stream, and is responsible + * for closing it after finishing decompression. + */ + +void zm_jpeg_mem_src( j_decompress_ptr cinfo, const JOCTET *inbuffer, int inbuffer_size ) +{ + mem_src_ptr src; + + /* The source object and input buffer are made permanent so that a series + * of JPEG images can be read from the same file by calling zm_jpeg_mem_src + * only before the first one. (If we discarded the buffer at the end of + * one image, we'd likely lose the start of the next one.) + * This makes it unsafe to use this manager and a different source + * manager serially with the same JPEG object. Caveat programmer. + */ + if ( cinfo->src == NULL ) + { + /* first time for this JPEG object? */ + cinfo->src = (struct jpeg_source_mgr *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(mem_source_mgr)); + src = (mem_src_ptr) cinfo->src; + src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); + src->inbuffer_size_hwm = inbuffer_size; + } + else + { + src = (mem_src_ptr) cinfo->src; + if ( src->inbuffer_size_hwm < inbuffer_size ) + { + src->buffer = (JOCTET *)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, inbuffer_size * SIZEOF(JOCTET)); + src->inbuffer_size_hwm = inbuffer_size; + } + } + + src = (mem_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */ + src->pub.term_source = term_source; + src->inbuffer = (JOCTET *)inbuffer; + src->inbuffer_size = inbuffer_size; + src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ + src->pub.next_input_byte = NULL; /* until buffer loaded */ +} + +void zm_use_std_huff_tables( j_decompress_ptr cinfo ) { + /* JPEG standard Huffman tables (cf. JPEG standard section K.3) */ + /* IMPORTANT: these are only valid for 8-bit data precision! */ + static const JHUFF_TBL dclumin = { + { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + 0 + }; + static const JHUFF_TBL dcchrome = { + { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + 0 + }; + static const JHUFF_TBL aclumin = { + { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }, + { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, + 0 + }; + static const JHUFF_TBL acchrome = { + { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }, + { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa }, + 0 + }; + + cinfo->dc_huff_tbl_ptrs[0] = (JHUFF_TBL*)&dclumin; + cinfo->dc_huff_tbl_ptrs[1] = (JHUFF_TBL*)&dcchrome; + cinfo->ac_huff_tbl_ptrs[0] = (JHUFF_TBL*)&aclumin; + cinfo->ac_huff_tbl_ptrs[1] = (JHUFF_TBL*)&acchrome; + +} + +} diff --git a/src/zm_jpeg.h b/src/zm_jpeg.h new file mode 100644 index 000000000..b4bec52b2 --- /dev/null +++ b/src/zm_jpeg.h @@ -0,0 +1,50 @@ +/* + * ZoneMinder Jpeg Interface, $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. +*/ + + +#include + +#include "jinclude.h" +#include "jpeglib.h" +#include "jerror.h" + +// Stop complaints about deuplicate definitions +#undef HAVE_STDLIB_H +#undef HAVE_STDDEF_H + +extern "C" +{ +/* Stuff for overriden error handlers */ +struct zm_error_mgr +{ + struct jpeg_error_mgr pub; + jmp_buf setjmp_buffer; +}; + +typedef struct zm_error_mgr *zm_error_ptr; + +void zm_jpeg_error_exit( j_common_ptr cinfo ); +void zm_jpeg_emit_message( j_common_ptr cinfo, int msg_level ); + +// Prototypes for memory compress/decompression object */ +void zm_jpeg_mem_src(j_decompress_ptr cinfo, const JOCTET *inbuffer, int inbuffer_size ); +void zm_jpeg_mem_dest(j_compress_ptr cinfo, JOCTET *outbuffer, int *outbuffer_size ); + +void zm_use_std_huff_tables( j_decompress_ptr cinfo ); +} diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp new file mode 100644 index 000000000..73aff87aa --- /dev/null +++ b/src/zm_local_camera.cpp @@ -0,0 +1,2174 @@ +// +// ZoneMinder Local Camera Class Implementation, $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. +// + +#include "zm.h" + +#if ZM_HAS_V4L + +#include "zm_local_camera.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int BigEndian; + +static int vidioctl( int fd, int request, void *arg ) +{ + int result = -1; + do + { + result = ioctl( fd, request, arg ); + } while ( result == -1 && errno == EINTR ); + return( result ); +} + +#if HAVE_LIBSWSCALE +static PixelFormat getFfPixFormatFromV4lPalette( int v4l_version, int palette ) +{ + PixelFormat pixFormat = PIX_FMT_NONE; + +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + switch( palette ) + { +#ifdef V4L2_PIX_FMT_RGB444 + case V4L2_PIX_FMT_RGB444 : + pixFormat = PIX_FMT_RGB444; + break; +#endif // V4L2_PIX_FMT_RGB444 + case V4L2_PIX_FMT_RGB555 : + pixFormat = PIX_FMT_RGB555; + break; + case V4L2_PIX_FMT_RGB565 : + pixFormat = PIX_FMT_RGB565; + break; + case V4L2_PIX_FMT_BGR24 : + pixFormat = PIX_FMT_BGR24; + break; + case V4L2_PIX_FMT_RGB24 : + pixFormat = PIX_FMT_RGB24; + break; + case V4L2_PIX_FMT_BGR32 : + pixFormat = PIX_FMT_BGRA; + break; + case V4L2_PIX_FMT_RGB32 : + pixFormat = PIX_FMT_ARGB; + break; + case V4L2_PIX_FMT_GREY : + pixFormat = PIX_FMT_GRAY8; + break; + case V4L2_PIX_FMT_YUYV : + pixFormat = PIX_FMT_YUYV422; + break; + case V4L2_PIX_FMT_YUV422P : + pixFormat = PIX_FMT_YUV422P; + break; + case V4L2_PIX_FMT_YUV411P : + pixFormat = PIX_FMT_YUV411P; + break; +#ifdef V4L2_PIX_FMT_YUV444 + case V4L2_PIX_FMT_YUV444 : + pixFormat = PIX_FMT_YUV444P; + break; +#endif // V4L2_PIX_FMT_YUV444 + case V4L2_PIX_FMT_YUV410 : + pixFormat = PIX_FMT_YUV410P; + break; + case V4L2_PIX_FMT_YUV420 : + pixFormat = PIX_FMT_YUV420P; + break; + case V4L2_PIX_FMT_JPEG : + case V4L2_PIX_FMT_MJPEG : + pixFormat = PIX_FMT_YUVJ444P; + break; + // These don't seem to have ffmpeg equivalents + // See if you can match any of the ones in the default clause below!? + case V4L2_PIX_FMT_UYVY : + case V4L2_PIX_FMT_RGB332 : + case V4L2_PIX_FMT_RGB555X : + case V4L2_PIX_FMT_RGB565X : + //case V4L2_PIX_FMT_Y16 : + //case V4L2_PIX_FMT_PAL8 : + case V4L2_PIX_FMT_YVU410 : + case V4L2_PIX_FMT_YVU420 : + case V4L2_PIX_FMT_Y41P : + //case V4L2_PIX_FMT_YUV555 : + //case V4L2_PIX_FMT_YUV565 : + //case V4L2_PIX_FMT_YUV32 : + case V4L2_PIX_FMT_NV12 : + case V4L2_PIX_FMT_NV21 : + case V4L2_PIX_FMT_YYUV : + case V4L2_PIX_FMT_HI240 : + case V4L2_PIX_FMT_HM12 : + //case V4L2_PIX_FMT_SBGGR8 : + //case V4L2_PIX_FMT_SGBRG8 : + //case V4L2_PIX_FMT_SBGGR16 : + case V4L2_PIX_FMT_DV : + case V4L2_PIX_FMT_MPEG : + case V4L2_PIX_FMT_WNVA : + case V4L2_PIX_FMT_SN9C10X : + case V4L2_PIX_FMT_PWC1 : + case V4L2_PIX_FMT_PWC2 : + case V4L2_PIX_FMT_ET61X251 : + //case V4L2_PIX_FMT_SPCA501 : + //case V4L2_PIX_FMT_SPCA505 : + //case V4L2_PIX_FMT_SPCA508 : + //case V4L2_PIX_FMT_SPCA561 : + //case V4L2_PIX_FMT_PAC207 : + //case V4L2_PIX_FMT_PJPG : + //case V4L2_PIX_FMT_YVYU : + default : + { + Fatal( "Can't find swscale format for palette %d", palette ); + break; + // These are all spare and may match some of the above + pixFormat = PIX_FMT_YUVJ420P; + pixFormat = PIX_FMT_YUVJ422P; + pixFormat = PIX_FMT_XVMC_MPEG2_MC; + pixFormat = PIX_FMT_XVMC_MPEG2_IDCT; + pixFormat = PIX_FMT_UYVY422; + pixFormat = PIX_FMT_UYYVYY411; + pixFormat = PIX_FMT_BGR565; + pixFormat = PIX_FMT_BGR555; + pixFormat = PIX_FMT_BGR8; + pixFormat = PIX_FMT_BGR4; + pixFormat = PIX_FMT_BGR4_BYTE; + pixFormat = PIX_FMT_RGB8; + pixFormat = PIX_FMT_RGB4; + pixFormat = PIX_FMT_RGB4_BYTE; + pixFormat = PIX_FMT_NV12; + pixFormat = PIX_FMT_NV21; + pixFormat = PIX_FMT_RGB32_1; + pixFormat = PIX_FMT_BGR32_1; + pixFormat = PIX_FMT_GRAY16BE; + pixFormat = PIX_FMT_GRAY16LE; + pixFormat = PIX_FMT_YUV440P; + pixFormat = PIX_FMT_YUVJ440P; + pixFormat = PIX_FMT_YUVA420P; + //pixFormat = PIX_FMT_VDPAU_H264; + //pixFormat = PIX_FMT_VDPAU_MPEG1; + //pixFormat = PIX_FMT_VDPAU_MPEG2; + } + } + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + switch( palette ) + { + case VIDEO_PALETTE_RGB32 : + if(BigEndian) + pixFormat = PIX_FMT_ARGB; + else + pixFormat = PIX_FMT_BGRA; + break; + case VIDEO_PALETTE_RGB24 : + if(BigEndian) + pixFormat = PIX_FMT_RGB24; + else + pixFormat = PIX_FMT_BGR24; + break; + case VIDEO_PALETTE_GREY : + pixFormat = PIX_FMT_GRAY8; + break; + case VIDEO_PALETTE_RGB555 : + pixFormat = PIX_FMT_RGB555; + break; + case VIDEO_PALETTE_RGB565 : + pixFormat = PIX_FMT_RGB565; + break; + case VIDEO_PALETTE_YUYV : + case VIDEO_PALETTE_YUV422 : + pixFormat = PIX_FMT_YUYV422; + break; + case VIDEO_PALETTE_YUV422P : + pixFormat = PIX_FMT_YUV422P; + break; + case VIDEO_PALETTE_YUV420P : + pixFormat = PIX_FMT_YUV420P; + break; + default : + { + Fatal( "Can't find swscale format for palette %d", palette ); + break; + // These are all spare and may match some of the above + pixFormat = PIX_FMT_YUVJ420P; + pixFormat = PIX_FMT_YUVJ422P; + pixFormat = PIX_FMT_YUVJ444P; + pixFormat = PIX_FMT_XVMC_MPEG2_MC; + pixFormat = PIX_FMT_XVMC_MPEG2_IDCT; + pixFormat = PIX_FMT_UYVY422; + pixFormat = PIX_FMT_UYYVYY411; + pixFormat = PIX_FMT_BGR565; + pixFormat = PIX_FMT_BGR555; + pixFormat = PIX_FMT_BGR8; + pixFormat = PIX_FMT_BGR4; + pixFormat = PIX_FMT_BGR4_BYTE; + pixFormat = PIX_FMT_RGB8; + pixFormat = PIX_FMT_RGB4; + pixFormat = PIX_FMT_RGB4_BYTE; + pixFormat = PIX_FMT_NV12; + pixFormat = PIX_FMT_NV21; + pixFormat = PIX_FMT_RGB32_1; + pixFormat = PIX_FMT_BGR32_1; + pixFormat = PIX_FMT_GRAY16BE; + pixFormat = PIX_FMT_GRAY16LE; + pixFormat = PIX_FMT_YUV440P; + pixFormat = PIX_FMT_YUVJ440P; + pixFormat = PIX_FMT_YUVA420P; + //pixFormat = PIX_FMT_VDPAU_H264; + //pixFormat = PIX_FMT_VDPAU_MPEG1; + //pixFormat = PIX_FMT_VDPAU_MPEG2; + } + } + } +#endif // ZM_HAS_V4L1 + return( pixFormat ); +} +#endif // HAVE_LIBSWSCALE + +#if ZM_HAS_V4L2 +static char palette_desc[32]; +/* Automatic format selection prefered formats */ +static const uint32_t prefered_rgb32_formats[] = {V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_YUV422P, V4L2_PIX_FMT_YUV420}; +static const uint32_t prefered_rgb24_formats[] = {V4L2_PIX_FMT_BGR24, V4L2_PIX_FMT_RGB24, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_YUV422P, V4L2_PIX_FMT_YUV420}; +static const uint32_t prefered_gray8_formats[] = {V4L2_PIX_FMT_GREY, V4L2_PIX_FMT_YUYV, V4L2_PIX_FMT_UYVY, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_MJPEG, V4L2_PIX_FMT_YUV422P, V4L2_PIX_FMT_YUV420}; +#endif + + +int LocalCamera::camera_count = 0; +int LocalCamera::channel_count = 0; +int LocalCamera::channels[VIDEO_MAX_FRAME]; +int LocalCamera::standards[VIDEO_MAX_FRAME]; + +int LocalCamera::vid_fd = -1; + +int LocalCamera::v4l_version = 0; +#if ZM_HAS_V4L2 +LocalCamera::V4L2Data LocalCamera::v4l2_data; +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 +LocalCamera::V4L1Data LocalCamera::v4l1_data; +#endif // ZM_HAS_V4L1 + +#if HAVE_LIBSWSCALE +AVFrame **LocalCamera::capturePictures = 0; +#endif // HAVE_LIBSWSCALE + +LocalCamera *LocalCamera::last_camera = NULL; + +LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras) : + Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + device( p_device ), + channel( p_channel ), + standard( p_standard ), + palette( p_palette ), + channel_index( 0 ), + extras ( p_extras ) +{ + // If we are the first, or only, input on this device then + // do the initial opening etc + device_prime = (camera_count++ == 0); + v4l_version = (p_method=="v4l2"?2:1); + + if ( capture ) + { + if ( device_prime ) + { + Debug( 2, "V4L support enabled, using V4L%d api", v4l_version ); + } + + if ( !last_camera || channel != last_camera->channel ) + { + // We are the first, or only, input that uses this channel + channel_prime = true; + channel_index = channel_count++; + channels[channel_index] = channel; + standards[channel_index] = standard; + } + else + { + // We are the second, or subsequent, input using this channel + channel_prime = false; + } + + } + + /* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */ + uint32_t checkval = 0xAABBCCDD; + if(*(unsigned char*)&checkval == 0xDD) { + BigEndian = 0; + Debug(2,"little-endian processor detected"); + } else if(*(unsigned char*)&checkval == 0xAA) { + BigEndian = 1; + Debug(2,"Big-endian processor detected"); + } else { + Error("Unable to detect the processor's endianness. Assuming little-endian."); + BigEndian = 0; + } + +#if ZM_HAS_V4L2 + if( v4l_version == 2 && palette == 0 ) { + /* Use automatic format selection */ + Debug(2,"Using automatic format selection"); + palette = AutoSelectFormat(colours); + if(palette == 0) { + Error("Automatic format selection failed. Falling back to YUYV"); + palette = V4L2_PIX_FMT_YUYV; + } else { + if(capture) { + Info("Selected capture palette: %s (%c%c%c%c)", palette_desc, palette&0xff, (palette>>8)&0xff, (palette>>16)&0xff, (palette>>24)&0xff); + } + } + } +#endif + + if( capture ) { + if ( last_camera ) { + if ( (p_method == "v4l2" && v4l_version != 2) || (p_method == "v4l1" && v4l_version != 1) ) + Fatal( "Different Video For Linux version used for monitors sharing same device" ); + + if ( standard != last_camera->standard ) + Warning( "Different video standards defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + + if ( palette != last_camera->palette ) + Warning( "Different video palettes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + + if ( width != last_camera->width || height != last_camera->height ) + Warning( "Different capture sizes defined for monitors sharing same device, results may be unpredictable or completely wrong" ); + } + } + +#if HAVE_LIBSWSCALE + if( capture ) { + /* Get ffmpeg pixel format based on capture palette and endianness */ + capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette ); + imagePixFormat = PIX_FMT_NONE; + } +#endif // HAVE_LIBSWSCALE + + /* V4L2 format matching */ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) { + /* Try to find a match for the selected palette and target colourspace */ + + /* RGB32 palette and 32bit target colourspace */ + if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + + /* BGR32 palette and 32bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + + /* RGB24 palette and 24bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + + /* BGR24 palette and 24bit target colourspace */ + } else if(palette == V4L2_PIX_FMT_BGR24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGR; + + /* Grayscale palette and grayscale target colourspace */ + } else if(palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + } else { + if( capture ) + Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); +#if HAVE_LIBSWSCALE + /* Try using swscale for the conversion */ + conversion_type = 1; + Debug(2,"Using swscale for image conversion"); + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + if( capture ) { + if(!sws_isSupportedInput(capturePixFormat)) { + Error("swscale does not support the used capture format: %c%c%c%c",(capturePixFormat)&0xff,((capturePixFormat>>8)&0xff),((capturePixFormat>>16)&0xff),((capturePixFormat>>24)&0xff)); + conversion_type = 2; /* Try ZM format conversions */ + } + if(!sws_isSupportedOutput(imagePixFormat)) { + Error("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + conversion_type = 2; /* Try ZM format conversions */ + } + } +#else + /* Don't have swscale, see what we can do */ + conversion_type = 2; +#endif + /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ + if(colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) { + conversion_type = 2; + } + + /* JPEG */ + if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + Debug(2,"Using JPEG image decoding"); + conversion_type = 3; + } + + if(conversion_type == 2) { + Debug(2,"Using ZM for image conversion"); + if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8) { + conversion_fptr = &std_convert_argb_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) { + conversion_fptr = &std_convert_bgra_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) { + /* Fast YUYV->Grayscale conversion by extracting the Y channel */ + if(config.cpu_extensions && sseversion >= 35) { + conversion_fptr = &ssse3_convert_yuyv_gray8; + Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); + } else { + conversion_fptr = &std_convert_yuyv_gray8; + Debug(2,"Using standard YUYV->grayscale fast conversion"); + } + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_yuyv_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_yuyv_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb555_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb555_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb565_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb565_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else { + Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + } + } + } + } +#endif // ZM_HAS_V4L2 + + /* V4L1 format matching */ +#if ZM_HAS_V4L1 + if ( v4l_version == 1) { + /* Try to find a match for the selected palette and target colourspace */ + + /* RGB32 palette and 32bit target colourspace */ + if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + if(BigEndian) { + subpixelorder = ZM_SUBPIX_ORDER_ARGB; + } else { + subpixelorder = ZM_SUBPIX_ORDER_BGRA; + } + + /* RGB24 palette and 24bit target colourspace */ + } else if(palette == VIDEO_PALETTE_RGB24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + if(BigEndian) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else { + subpixelorder = ZM_SUBPIX_ORDER_BGR; + } + + /* Grayscale palette and grayscale target colourspace */ + } else if(palette == VIDEO_PALETTE_GREY && colours == ZM_COLOUR_GRAY8) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + } else { + if( capture ) + Info("No direct match for the selected palette and target colorspace. Format conversion is required, performance penalty expected"); +#if HAVE_LIBSWSCALE + /* Try using swscale for the conversion */ + conversion_type = 1; + Debug(2,"Using swscale for image conversion"); + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + if( capture ) { + if(!sws_isSupportedInput(capturePixFormat)) { + Error("swscale does not support the used capture format"); + conversion_type = 2; /* Try ZM format conversions */ + } + if(!sws_isSupportedOutput(imagePixFormat)) { + Error("swscale does not support the target format"); + conversion_type = 2; /* Try ZM format conversions */ + } + } +#else + /* Don't have swscale, see what we can do */ + conversion_type = 2; +#endif + /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ + if(colours == ZM_COLOUR_GRAY8 && (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422)) { + conversion_type = 2; + } + + if(conversion_type == 2) { + Debug(2,"Using ZM for image conversion"); + if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_GRAY8) { + if(BigEndian) { + conversion_fptr = &std_convert_argb_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else { + conversion_fptr = &std_convert_bgra_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8) { + /* Fast YUYV->Grayscale conversion by extracting the Y channel */ + if(config.cpu_extensions && sseversion >= 35) { + conversion_fptr = &ssse3_convert_yuyv_gray8; + Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); + } else { + conversion_fptr = &std_convert_yuyv_gray8; + Debug(2,"Using standard YUYV->grayscale fast conversion"); + } + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_yuyv_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_yuyv_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb555_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb555_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb565_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb565_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else { + Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + } + } + } + } +#endif // ZM_HAS_V4L1 + + last_camera = this; + Debug(3,"Selected subpixelorder: %d",subpixelorder); + +#if HAVE_LIBSWSCALE + /* Initialize swscale stuff */ + if(capture && conversion_type == 1) { + tmpPicture = avcodec_alloc_frame(); + if ( !tmpPicture ) + Fatal( "Could not allocate temporary picture" ); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } + + if(config.cpu_extensions && sseversion >= 20) { + imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL ); + } else { + imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + } + + if ( !imgConversionContext ) + Fatal( "Unable to initialise image scaling context" ); + + } +#endif +} + +LocalCamera::~LocalCamera() +{ + if ( device_prime && capture ) + Terminate(); + +#if HAVE_LIBSWSCALE + /* Clean up swscale stuff */ + if(capture && conversion_type == 1) { + sws_freeContext(imgConversionContext); + imgConversionContext = NULL; + + av_free(tmpPicture); + tmpPicture = NULL; + } +#endif +} + +void LocalCamera::Initialise() +{ +#if HAVE_LIBSWSCALE + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); +#endif // HAVE_LIBSWSCALE + + struct stat st; + + if ( stat( device.c_str(), &st ) < 0 ) + Fatal( "Failed to stat video device %s: %s", device.c_str(), strerror(errno) ); + + if ( !S_ISCHR(st.st_mode) ) + Fatal( "File %s is not device file: %s", device.c_str(), strerror(errno) ); + + Debug( 3, "Opening video device %s", device.c_str() ); + //if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 ) + if ( (vid_fd = open( device.c_str(), O_RDWR, 0 )) < 0 ) + Fatal( "Failed to open video device %s: %s", device.c_str(), strerror(errno) ); + +#if ZM_HAS_V4L2 + Debug( 2, "V4L2 support enabled, using V4L%d api", v4l_version ); + if ( v4l_version == 2 ) + { + struct v4l2_capability vid_cap; + + Debug( 3, "Checking video device capabilities" ); + if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) + Fatal( "Failed to query video device: %s", strerror(errno) ); + + if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ) + Fatal( "Video device is not video capture device" ); + + if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) ) + Fatal( "Video device does not support streaming i/o" ); + + Debug( 3, "Setting up video format" ); + + memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) ); + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 ) + Fatal( "Failed to get video format: %s", strerror(errno) ); + + Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); + Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); + Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); + Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); + Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); + Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); + Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); + Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); + Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); + + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_data.fmt.fmt.pix.width = width; + v4l2_data.fmt.fmt.pix.height = height; + v4l2_data.fmt.fmt.pix.pixelformat = palette; + + if ( (extras & 0xff) != 0 ) + { + v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff); + + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) + { + Warning( "Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff) ); + v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } + } else { + if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 ) { + Fatal( "Failed to set video format: %s", strerror(errno) ); + } + } + + /* Note VIDIOC_S_FMT may change width and height. */ + Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type ); + Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width ); + Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height ); + Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat ); + Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field ); + Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline ); + Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage ); + Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace ); + Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv ); + + /* Buggy driver paranoia. */ + unsigned int min; + min = v4l2_data.fmt.fmt.pix.width * 2; + if (v4l2_data.fmt.fmt.pix.bytesperline < min) + v4l2_data.fmt.fmt.pix.bytesperline = min; + min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height; + if (v4l2_data.fmt.fmt.pix.sizeimage < min) + v4l2_data.fmt.fmt.pix.sizeimage = min; + + v4l2_jpegcompression jpeg_comp; + if(palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + if( vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0 ) { + if(errno == EINVAL) { + Debug(2, "JPEG compression options are not available"); + } else { + Warning("Failed to get JPEG compression options: %s", strerror(errno) ); + } + } else { + /* Set flags and quality. MJPEG should not have the huffman tables defined */ + if(palette == V4L2_PIX_FMT_MJPEG) { + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; + } else { + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT; + } + jpeg_comp.quality = 85; + + /* Update the JPEG options */ + if( vidioctl( vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp ) < 0 ) { + Warning("Failed to set JPEG compression options: %s", strerror(errno) ); + } else { + if(vidioctl( vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp ) < 0) { + Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno) ); + } else { + Debug(4, "JPEG quality: %d",jpeg_comp.quality); + Debug(4, "JPEG markers: %#x",jpeg_comp.jpeg_markers); + } + } + } + } + + Debug( 3, "Setting up request buffers" ); + + memset( &v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs) ); + if ( channel_count > 1 ) + if ( config.v4l_multi_buffer ) + v4l2_data.reqbufs.count = 2*channel_count; + else + v4l2_data.reqbufs.count = 1; + else + v4l2_data.reqbufs.count = 8; + v4l2_data.reqbufs.type = v4l2_data.fmt.type; + v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP; + + if ( vidioctl( vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs ) < 0 ) + { + if ( errno == EINVAL ) + { + Fatal( "Unable to initialise memory mapping, unsupported in device" ); + } + else + { + Fatal( "Unable to initialise memory mapping: %s", strerror(errno) ); + } + } + + if ( v4l2_data.reqbufs.count < (config.v4l_multi_buffer?2:1) ) + Fatal( "Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count ); + + Debug( 3, "Setting up %d data buffers", v4l2_data.reqbufs.count ); + + v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count]; +#if HAVE_LIBSWSCALE + capturePictures = new AVFrame *[v4l2_data.reqbufs.count]; +#endif // HAVE_LIBSWSCALE + for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) + { + struct v4l2_buffer vid_buf; + + memset( &vid_buf, 0, sizeof(vid_buf) ); + + //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vid_buf.type = v4l2_data.fmt.type; + //vid_buf.memory = V4L2_MEMORY_MMAP; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = i; + + if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) < 0 ) + Fatal( "Unable to query video buffer: %s", strerror(errno) ); + + v4l2_data.buffers[i].length = vid_buf.length; + v4l2_data.buffers[i].start = mmap( NULL, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset ); + + if ( v4l2_data.buffers[i].start == MAP_FAILED ) + Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno ); + +#if HAVE_LIBSWSCALE + capturePictures[i] = avcodec_alloc_frame(); + if ( !capturePictures[i] ) + Fatal( "Could not allocate picture" ); + avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height ); +#endif // HAVE_LIBSWSCALE + } + + Debug( 3, "Configuring video source" ); + + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 ) + { + Fatal( "Failed to set camera source %d: %s", channel, strerror(errno) ); + } + + struct v4l2_input input; + v4l2_std_id stdId; + + memset( &input, 0, sizeof(input) ); + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + Fatal( "Failed to enumerate input %d: %s", channel, strerror(errno) ); + } + + if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) + { + Fatal( "Device does not support video standard %d", standard ); + } + + stdId = standard; + if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) + { + Fatal( "Failed to set video standard %d: %s", standard, strerror(errno) ); + } + + Contrast(contrast); + Brightness(brightness); + Hue(hue); + Colour(colour); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + Debug( 3, "Configuring picture attributes" ); + + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(vid_pic) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + Fatal( "Failed to get picture attributes: %s", strerror(errno) ); + + Debug( 4, "Old P:%d", vid_pic.palette ); + Debug( 4, "Old D:%d", vid_pic.depth ); + Debug( 4, "Old B:%d", vid_pic.brightness ); + Debug( 4, "Old h:%d", vid_pic.hue ); + Debug( 4, "Old Cl:%d", vid_pic.colour ); + Debug( 4, "Old Cn:%d", vid_pic.contrast ); + + switch (vid_pic.palette = palette) + { + case VIDEO_PALETTE_RGB32 : + { + vid_pic.depth = 32; + break; + } + case VIDEO_PALETTE_RGB24 : + { + vid_pic.depth = 24; + break; + } + case VIDEO_PALETTE_GREY : + { + vid_pic.depth = 8; + break; + } + case VIDEO_PALETTE_RGB565 : + case VIDEO_PALETTE_YUYV : + case VIDEO_PALETTE_YUV422 : + case VIDEO_PALETTE_YUV420P : + case VIDEO_PALETTE_YUV422P : + default: + { + vid_pic.depth = 16; + break; + } + } + + if ( brightness >= 0 ) vid_pic.brightness = brightness; + if ( hue >= 0 ) vid_pic.hue = hue; + if ( colour >= 0 ) vid_pic.colour = colour; + if ( contrast >= 0 ) vid_pic.contrast = contrast; + + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); + } + + Debug( 3, "Configuring window attributes" ); + + struct video_window vid_win; + memset( &vid_win, 0, sizeof(vid_win) ); + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) + { + Error( "Failed to get window attributes: %s", strerror(errno) ); + exit(-1); + } + Debug( 4, "Old X:%d", vid_win.x ); + Debug( 4, "Old Y:%d", vid_win.y ); + Debug( 4, "Old W:%d", vid_win.width ); + Debug( 4, "Old H:%d", vid_win.height ); + + vid_win.x = 0; + vid_win.y = 0; + vid_win.width = width; + vid_win.height = height; + vid_win.flags &= ~VIDEO_WINDOW_INTERLACE; + + if ( ioctl( vid_fd, VIDIOCSWIN, &vid_win ) < 0 ) + { + Error( "Failed to set window attributes: %s", strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); + } + + Info( "vid_win.width = %08x", vid_win.width ); + Info( "vid_win.height = %08x", vid_win.height ); + Info( "vid_win.flags = %08x", vid_win.flags ); + + Debug( 3, "Setting up request buffers" ); + if ( ioctl( vid_fd, VIDIOCGMBUF, &v4l1_data.frames ) < 0 ) + Fatal( "Failed to setup memory: %s", strerror(errno) ); + if ( channel_count > 1 && !config.v4l_multi_buffer ) + v4l1_data.frames.frames = 1; + v4l1_data.buffers = new video_mmap[v4l1_data.frames.frames]; + Debug( 4, "vmb.frames = %d", v4l1_data.frames.frames ); + Debug( 4, "vmb.size = %d", v4l1_data.frames.size ); + + Debug( 3, "Setting up %d frame buffers", v4l1_data.frames.frames ); + + v4l1_data.bufptr = (unsigned char *)mmap( 0, v4l1_data.frames.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, 0 ); + if ( v4l1_data.bufptr == MAP_FAILED ) + Fatal( "Could not mmap video: %s", strerror(errno) ); + +#if HAVE_LIBSWSCALE + capturePictures = new AVFrame *[v4l1_data.frames.frames]; + for ( int i = 0; i < v4l1_data.frames.frames; i++ ) + { + v4l1_data.buffers[i].frame = i; + v4l1_data.buffers[i].width = width; + v4l1_data.buffers[i].height = height; + v4l1_data.buffers[i].format = palette; + + capturePictures[i] = avcodec_alloc_frame(); + if ( !capturePictures[i] ) + Fatal( "Could not allocate picture" ); + avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height ); + } +#endif // HAVE_LIBSWSCALE + + Debug( 3, "Configuring video source" ); + + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(vid_src) ); + vid_src.channel = channel; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) + Fatal( "Failed to get camera source: %s", strerror(errno) ); + + Debug( 4, "Old C:%d", vid_src.channel ); + Debug( 4, "Old F:%d", vid_src.norm ); + Debug( 4, "Old Fl:%x", vid_src.flags ); + Debug( 4, "Old T:%d", vid_src.type ); + + vid_src.norm = standard; + vid_src.flags = 0; + vid_src.type = VIDEO_TYPE_CAMERA; + if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) + { + Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); + if ( config.strict_video_config ) + exit(-1); + } + + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 ) + Fatal( "Failed to get window data: %s", strerror(errno) ); + + Info( "vid_win.width = %08x", vid_win.width ); + Info( "vid_win.height = %08x", vid_win.height ); + Info( "vid_win.flags = %08x", vid_win.flags ); + + Debug( 4, "New X:%d", vid_win.x ); + Debug( 4, "New Y:%d", vid_win.y ); + Debug( 4, "New W:%d", vid_win.width ); + Debug( 4, "New H:%d", vid_win.height ); + + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + Fatal( "Failed to get window data: %s", strerror(errno) ); + + Debug( 4, "New P:%d", vid_pic.palette ); + Debug( 4, "New D:%d", vid_pic.depth ); + Debug( 4, "New B:%d", vid_pic.brightness ); + Debug( 4, "New h:%d", vid_pic.hue ); + Debug( 4, "New Cl:%d", vid_pic.colour ); + Debug( 4, "New Cn:%d", vid_pic.contrast ); + } +#endif // ZM_HAS_V4L1 +} + +void LocalCamera::Terminate() +{ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + Debug( 3, "Terminating video stream" ); + //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + // enum v4l2_buf_type type = v4l2_data.fmt.type; + enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; + if ( vidioctl( vid_fd, VIDIOC_STREAMOFF, &type ) < 0 ) + Error( "Failed to stop capture stream: %s", strerror(errno) ); + + Debug( 3, "Unmapping video buffers" ); + for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) { +#if HAVE_LIBSWSCALE + /* Free capture pictures */ + av_free(capturePictures[i]); + capturePictures[i] = NULL; +#endif + if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 ) + Error( "Failed to munmap buffer %d: %s", i, strerror(errno) ); + } + + } + else +#endif // ZM_HAS_V4L2 + + +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { +#if HAVE_LIBSWSCALE + for(unsigned int i=0; i < v4l1_data.frames.frames; i++) { + /* Free capture pictures */ + av_free(capturePictures[i]); + capturePictures[i] = NULL; + } +#endif + + Debug( 3, "Unmapping video buffers" ); + if ( munmap((char*)v4l1_data.bufptr, v4l1_data.frames.size) < 0 ) + Error( "Failed to munmap buffers: %s", strerror(errno) ); + + delete[] v4l1_data.buffers; + } +#endif // ZM_HAS_V4L1 + + close( vid_fd ); + +} + +uint32_t LocalCamera::AutoSelectFormat(int p_colours) { + /* Automatic format selection */ + uint32_t selected_palette = 0; +#if ZM_HAS_V4L2 + char fmt_desc[64][32]; + uint32_t fmt_fcc[64]; + v4l2_fmtdesc fmtinfo; + unsigned int nIndex = 0; + //int nRet = 0; // compiler say it isn't used + int enum_fd; + + /* Open the device */ + if ((enum_fd = open( device.c_str(), O_RDWR, 0 )) < 0) { + Error( "Automatic format selection failed to open video device %s: %s", device.c_str(), strerror(errno) ); + return selected_palette; + } + + /* Enumerate available formats */ + memset(&fmtinfo, 0, sizeof(fmtinfo)); + fmtinfo.index = nIndex; + fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + while(vidioctl( enum_fd, VIDIOC_ENUM_FMT, &fmtinfo ) >= 0) { + /* Got a format. Copy it to the array */ + strcpy(fmt_desc[nIndex], (const char*)(fmtinfo.description)); + fmt_fcc[nIndex] = fmtinfo.pixelformat; + + Debug(6, "Got format: %s (%c%c%c%c) at index %d",fmt_desc[nIndex],fmt_fcc[nIndex]&0xff, (fmt_fcc[nIndex]>>8)&0xff, (fmt_fcc[nIndex]>>16)&0xff, (fmt_fcc[nIndex]>>24)&0xff ,nIndex); + + /* Proceed to the next index */ + memset(&fmtinfo, 0, sizeof(fmtinfo)); + fmtinfo.index = ++nIndex; + fmtinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + } + + /* Select format */ + int nIndexUsed = -1; + int n_preferedformats = 0; + const uint32_t* preferedformats; + if(p_colours == ZM_COLOUR_RGB32) { + /* 32bit */ + preferedformats = prefered_rgb32_formats; + n_preferedformats = sizeof(prefered_rgb32_formats) / sizeof(uint32_t); + } else if(p_colours == ZM_COLOUR_GRAY8) { + /* Grayscale */ + preferedformats = prefered_gray8_formats; + n_preferedformats = sizeof(prefered_gray8_formats) / sizeof(uint32_t); + } else { + /* Assume 24bit */ + preferedformats = prefered_rgb24_formats; + n_preferedformats = sizeof(prefered_rgb24_formats) / sizeof(uint32_t); + } + for( unsigned int i=0; i < (unsigned int)n_preferedformats && nIndexUsed < 0; i++ ) { + for( unsigned int j=0; j < nIndex; j++ ) { + if( preferedformats[i] == fmt_fcc[j] ) { + /* Found a format! */ + nIndexUsed = j; + break; + } + } + } + + /* Have we found a match? */ + if(nIndexUsed >= 0) { + /* Found a match */ + selected_palette = fmt_fcc[nIndexUsed]; + strcpy(palette_desc,fmt_desc[nIndexUsed]); + } + + /* Close the device */ + close(enum_fd); + +#endif /* ZM_HAS_V4L2 */ + return selected_palette; +} + + +#define capString(test,prefix,yesString,noString,capability) \ + (test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n") + +bool LocalCamera::GetCurrentSettings( const char *device, char *output, int version, bool verbose ) +{ + output[0] = 0; + + char queryDevice[PATH_MAX] = ""; + int devIndex = 0; + do + { + if ( device ) + strcpy( queryDevice, device ); + else + sprintf( queryDevice, "/dev/video%d", devIndex ); + if ( (vid_fd = open(queryDevice, O_RDWR)) <= 0 ) + { + if ( device ) + { + Error( "Failed to open video device %s: %s", queryDevice, strerror(errno) ); + if ( verbose ) + sprintf( output+strlen(output), "Error, failed to open video device %s: %s\n", queryDevice, strerror(errno) ); + else + sprintf( output+strlen(output), "error%d\n", errno ); + return( false ); + } + else + { + return( true ); + } + } + if ( verbose ) + sprintf( output+strlen(output), "Video Device: %s\n", queryDevice ); + else + sprintf( output+strlen(output), "d:%s|", queryDevice ); + +#if ZM_HAS_V4L2 + if ( version == 2 ) + { + struct v4l2_capability vid_cap; + if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 ) + { + Error( "Failed to query video device: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to query video capabilities %s: %s\n", queryDevice, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + + if ( verbose ) + { + sprintf( output+strlen(output), "General Capabilities\n" ); + sprintf( output+strlen(output), " Driver: %s\n", vid_cap.driver ); + sprintf( output+strlen(output), " Card: %s\n", vid_cap.card ); + sprintf( output+strlen(output), " Bus: %s\n", vid_cap.bus_info ); + sprintf( output+strlen(output), " Version: %u.%u.%u\n", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); + sprintf( output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.capabilities, + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)" ), + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output" ), + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OVERLAY, " ", "Supports", "Does not support", "frame buffer overlay" ), + capString( vid_cap.capabilities&V4L2_CAP_VBI_CAPTURE, " ", "Supports", "Does not support", "VBI capture" ), + capString( vid_cap.capabilities&V4L2_CAP_VBI_OUTPUT, " ", "Supports", "Does not support", "VBI output" ), + capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_CAPTURE, " ", "Supports", "Does not support", "sliced VBI capture" ), + capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_OUTPUT, " ", "Supports", "Does not support", "sliced VBI output" ), +#ifdef V4L2_CAP_VIDEO_OUTPUT_OVERLAY + capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT_OVERLAY, " ", "Supports", "Does not support", "video output overlay" ), +#else // V4L2_CAP_VIDEO_OUTPUT_OVERLAY + "", +#endif // V4L2_CAP_VIDEO_OUTPUT_OVERLAY + capString( vid_cap.capabilities&V4L2_CAP_TUNER, " ", "Has", "Does not have", "tuner" ), + capString( vid_cap.capabilities&V4L2_CAP_AUDIO, " ", "Has", "Does not have", "audio in and/or out" ), + capString( vid_cap.capabilities&V4L2_CAP_RADIO, " ", "Has", "Does not have", "radio" ), + capString( vid_cap.capabilities&V4L2_CAP_READWRITE, " ", "Supports", "Does not support", "read/write i/o (X)" ), + capString( vid_cap.capabilities&V4L2_CAP_ASYNCIO, " ", "Supports", "Does not support", "async i/o" ), + capString( vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)" ) + ); + } + else + { + sprintf( output+strlen(output), "D:%s|", vid_cap.driver ); + sprintf( output+strlen(output), "C:%s|", vid_cap.card ); + sprintf( output+strlen(output), "B:%s|", vid_cap.bus_info ); + sprintf( output+strlen(output), "V:%u.%u.%u|", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff ); + sprintf( output+strlen(output), "T:0x%x|", vid_cap.capabilities ); + } + + if ( verbose ) + sprintf( output+strlen(output), " Standards:\n" ); + else + sprintf( output+strlen(output), "S:" ); + struct v4l2_standard standard; + int standardIndex = 0; + do + { + memset( &standard, 0, sizeof(standard) ); + standard.index = standardIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMSTD, &standard ) < 0 ) + { + if ( errno == EINVAL ) + { + standardIndex = -1; + break; + } + else + { + Error( "Failed to enumerate standard %d: %s", standard.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate standard %d: %s\n", standard.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + if ( verbose ) + sprintf( output+strlen(output), " %s\n", standard.name ); + else + sprintf( output+strlen(output), "%s/", standard.name ); + } + while ( standardIndex++ >= 0 ); + if ( !verbose && output[strlen(output)-1] == '/') + output[strlen(output)-1] = '|'; + + if ( verbose ) + sprintf( output+strlen(output), " Formats:\n" ); + else + sprintf( output+strlen(output), "F:" ); + struct v4l2_fmtdesc format; + int formatIndex = 0; + do + { + memset( &format, 0, sizeof(format) ); + format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + format.index = formatIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUM_FMT, &format ) < 0 ) + { + if ( errno == EINVAL ) + { + formatIndex = -1; + break; + } + else + { + Error( "Failed to enumerate format %d: %s", format.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + if ( verbose ) + sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); + else + sprintf( output+strlen(output), "%c%c%c%c/", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff ); + } + while ( formatIndex++ >= 0 ); + if ( !verbose ) + output[strlen(output)-1] = '|'; + + if(verbose) + sprintf( output+strlen(output), "Crop Capabilities\n" ); + + struct v4l2_cropcap cropcap; + memset( &cropcap, 0, sizeof(cropcap) ); + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 ) + { + if(errno != EINVAL) { + /* Failed querying crop capability, write error to the log and continue as if crop is not supported */ + Error( "Failed to query crop capabilities: %s", strerror(errno) ); + } + + if(verbose) { + sprintf( output+strlen(output), " Cropping is not supported\n"); + } else { + /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ + sprintf( output+strlen(output), "B:%dx%d|",0,0); + } + } else { + struct v4l2_crop crop; + memset( &crop, 0, sizeof(crop) ); + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if ( vidioctl( vid_fd, VIDIOC_G_CROP, &crop ) < 0 ) + { + if ( errno != EINVAL ) + { + /* Failed querying crop sizes, write error to the log and continue as if crop is not supported */ + Error( "Failed to query crop: %s", strerror(errno) ); + } + + if ( verbose ) { + sprintf( output+strlen(output), " Cropping is not supported\n"); + } else { + /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */ + sprintf( output+strlen(output), "B:%dx%d|",0,0); + } + } else { + /* Cropping supported */ + if ( verbose ) { + sprintf( output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height ); + sprintf( output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height ); + sprintf( output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height ); + } else { + sprintf( output+strlen(output), "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height ); + } + } + } /* Crop code */ + + struct v4l2_input input; + int inputIndex = 0; + do + { + memset( &input, 0, sizeof(input) ); + input.index = inputIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + if ( errno == EINVAL ) + { + break; + } + else + { + Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + } + while ( inputIndex++ >= 0 ); + + if ( verbose ) + sprintf( output+strlen(output), "Inputs: %d\n", inputIndex ); + else + sprintf( output+strlen(output), "I:%d|", inputIndex ); + + inputIndex = 0; + do + { + memset( &input, 0, sizeof(input) ); + input.index = inputIndex; + + if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 ) + { + if ( errno == EINVAL ) + { + inputIndex = -1; + break; + } + else + { + Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + } + + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &input.index ) < 0 ) + { + Error( "Failed to set video input %d: %s", input.index, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + + if ( verbose ) + { + sprintf( output+strlen(output), " Input %d\n", input.index ); + sprintf( output+strlen(output), " Name: %s\n", input.name ); + sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); + sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset ); + sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std ); + } + else + { + sprintf( output+strlen(output), "i%d:%s|", input.index, input.name ); + sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") ); + sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std ); + } + + if ( verbose ) + { + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) ); + sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) ); + } + else + { + sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 ); + sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 ); + sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 ); + sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 ); + } + } + while ( inputIndex++ >= 0 ); + if ( !verbose ) + output[strlen(output)-1] = '\n'; + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( version == 1 ) + { + struct video_capability vid_cap; + memset( &vid_cap, 0, sizeof(video_capability) ); + if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 ) + { + Error( "Failed to get video capabilities: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Video Capabilities\n" ); + sprintf( output+strlen(output), " Name: %s\n", vid_cap.name ); + sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type, + vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"", + vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"", + vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"", + vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"", + vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"", + vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"", + vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"", + vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"", + vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"", + vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"", + vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"", + vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"", + vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"", + vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":"" + ); + sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels ); + sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios ); + sprintf( output+strlen(output), " Maximum Width: %d\n", vid_cap.maxwidth ); + sprintf( output+strlen(output), " Maximum Height: %d\n", vid_cap.maxheight ); + sprintf( output+strlen(output), " Minimum Width: %d\n", vid_cap.minwidth ); + sprintf( output+strlen(output), " Minimum Height: %d\n", vid_cap.minheight ); + } + else + { + sprintf( output+strlen(output), "N:%s|", vid_cap.name ); + sprintf( output+strlen(output), "T:%d|", vid_cap.type ); + sprintf( output+strlen(output), "nC:%d|", vid_cap.channels ); + sprintf( output+strlen(output), "nA:%d|", vid_cap.audios ); + sprintf( output+strlen(output), "mxW:%d|", vid_cap.maxwidth ); + sprintf( output+strlen(output), "mxH:%d|", vid_cap.maxheight ); + sprintf( output+strlen(output), "mnW:%d|", vid_cap.minwidth ); + sprintf( output+strlen(output), "mnH:%d|", vid_cap.minheight ); + } + + struct video_window vid_win; + memset( &vid_win, 0, sizeof(video_window) ); + if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 ) + { + Error( "Failed to get window attributes: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get window attributes: %s\n", strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Window Attributes\n" ); + sprintf( output+strlen(output), " X Offset: %d\n", vid_win.x ); + sprintf( output+strlen(output), " Y Offset: %d\n", vid_win.y ); + sprintf( output+strlen(output), " Width: %d\n", vid_win.width ); + sprintf( output+strlen(output), " Height: %d\n", vid_win.height ); + } + else + { + sprintf( output+strlen(output), "X:%d|", vid_win.x ); + sprintf( output+strlen(output), "Y:%d|", vid_win.y ); + sprintf( output+strlen(output), "W:%d|", vid_win.width ); + sprintf( output+strlen(output), "H:%d|", vid_win.height ); + } + + struct video_picture vid_pic; + memset( &vid_cap, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get picture attributes: %s\n", strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Picture Attributes\n" ); + sprintf( output+strlen(output), " Palette: %d - %s\n", vid_pic.palette, + vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":( + vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":( + vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB24?"24bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB32?"32bit RGB":( + vid_pic.palette==VIDEO_PALETTE_RGB555?"555 15bit RGB":( + vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422 capture":( + vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( + vid_pic.palette==VIDEO_PALETTE_UYVY?"UVYV":( + vid_pic.palette==VIDEO_PALETTE_YUV420?"YUV420":( + vid_pic.palette==VIDEO_PALETTE_YUV411?"YUV411 capture":( + vid_pic.palette==VIDEO_PALETTE_RAW?"RAW capture (BT848)":( + vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":( + vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422":( + vid_pic.palette==VIDEO_PALETTE_YUV422P?"YUV 4:2:2 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":( + vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown" + )))))))))))))))))); + sprintf( output+strlen(output), " Colour Depth: %d\n", vid_pic.depth ); + sprintf( output+strlen(output), " Brightness: %d\n", vid_pic.brightness ); + sprintf( output+strlen(output), " Hue: %d\n", vid_pic.hue ); + sprintf( output+strlen(output), " Colour :%d\n", vid_pic.colour ); + sprintf( output+strlen(output), " Contrast: %d\n", vid_pic.contrast ); + sprintf( output+strlen(output), " Whiteness: %d\n", vid_pic.whiteness ); + } + else + { + sprintf( output+strlen(output), "P:%d|", vid_pic.palette ); + sprintf( output+strlen(output), "D:%d|", vid_pic.depth ); + sprintf( output+strlen(output), "B:%d|", vid_pic.brightness ); + sprintf( output+strlen(output), "h:%d|", vid_pic.hue ); + sprintf( output+strlen(output), "Cl:%d|", vid_pic.colour ); + sprintf( output+strlen(output), "Cn:%d|", vid_pic.contrast ); + sprintf( output+strlen(output), "w:%d|", vid_pic.whiteness ); + } + + for ( int chan = 0; chan < vid_cap.channels; chan++ ) + { + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(video_channel) ); + vid_src.channel = chan; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 ) + { + Error( "Failed to get channel %d attributes: %s", chan, strerror(errno) ); + if ( verbose ) + sprintf( output, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno) ); + else + sprintf( output, "error%d\n", errno ); + return( false ); + } + if ( verbose ) + { + sprintf( output+strlen(output), "Channel %d Attributes\n", chan ); + sprintf( output+strlen(output), " Name: %s\n", vid_src.name ); + sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel ); + sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags, + vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"", + vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":"" + ); + sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type, + vid_src.type==VIDEO_TYPE_TV?"TV":( + vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown" + )); + sprintf( output+strlen(output), " Format: %d - %s\n", vid_src.norm, + vid_src.norm==VIDEO_MODE_PAL?"PAL":( + vid_src.norm==VIDEO_MODE_NTSC?"NTSC":( + vid_src.norm==VIDEO_MODE_SECAM?"SECAM":( + vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown" + )))); + } + else + { + sprintf( output+strlen(output), "n%d:%s|", chan, vid_src.name ); + sprintf( output+strlen(output), "C%d:%d|", chan, vid_src.channel ); + sprintf( output+strlen(output), "Fl%d:%x|", chan, vid_src.flags ); + sprintf( output+strlen(output), "T%d:%d|", chan, vid_src.type ); + sprintf( output+strlen(output), "F%d:%d%s|", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," ); + } + } + if ( !verbose ) + output[strlen(output)-1] = '\n'; + } +#endif // ZM_HAS_V4L1 + close( vid_fd ); + if ( device ) + break; + } + while ( ++devIndex < 32 ); + return( true ); +} + +int LocalCamera::Brightness( int p_brightness ) +{ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_BRIGHTNESS; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) + { + if ( errno != EINVAL ) + Error( "Unable to query brightness: %s", strerror(errno) ) + else + Warning( "Brightness control is not suppported" ) + //Info( "Brightness 1 %d", vid_control.value ); + } + else if ( p_brightness >= 0 ) + { + vid_control.value = p_brightness; + + //Info( "Brightness 2 %d", vid_control.value ); + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) + { + if ( errno != ERANGE ) + Error( "Unable to set brightness: %s", strerror(errno) ) + else + Warning( "Given brightness value (%d) may be out-of-range", p_brightness ) + } + //Info( "Brightness 3 %d", vid_control.value ); + } + return( vid_control.value ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); + } + + if ( p_brightness >= 0 ) + { + vid_pic.brightness = p_brightness; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.brightness ); + } +#endif // ZM_HAS_V4L1 + return( -1 ); +} + +int LocalCamera::Hue( int p_hue ) +{ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_HUE; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) + { + if ( errno != EINVAL ) + Error( "Unable to query hue: %s", strerror(errno) ) + else + Warning( "Hue control is not suppported" ) + } + else if ( p_hue >= 0 ) + { + vid_control.value = p_hue; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) + { + if ( errno != ERANGE ) + Error( "Unable to set hue: %s", strerror(errno) ) + else + Warning( "Given hue value (%d) may be out-of-range", p_hue ) + } + } + return( vid_control.value ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); + } + + if ( p_hue >= 0 ) + { + vid_pic.hue = p_hue; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.hue ); + } +#endif // ZM_HAS_V4L1 + return( -1 ); +} + +int LocalCamera::Colour( int p_colour ) +{ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_SATURATION; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) + { + if ( errno != EINVAL ) + Error( "Unable to query saturation: %s", strerror(errno) ) + else + Warning( "Saturation control is not suppported" ) + } + else if ( p_colour >= 0 ) + { + vid_control.value = p_colour; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 ) + { + if ( errno != ERANGE ) + Error( "Unable to set saturation: %s", strerror(errno) ) + else + Warning( "Given saturation value (%d) may be out-of-range", p_colour ) + } + } + return( vid_control.value ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); + } + + if ( p_colour >= 0 ) + { + vid_pic.colour = p_colour; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.colour ); + } +#endif // ZM_HAS_V4L1 + return( -1 ); +} + +int LocalCamera::Contrast( int p_contrast ) +{ +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + struct v4l2_control vid_control; + + memset( &vid_control, 0, sizeof(vid_control) ); + vid_control.id = V4L2_CID_CONTRAST; + + if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 ) + { + if ( errno != EINVAL ) + Error( "Unable to query contrast: %s", strerror(errno) ) + else + Warning( "Contrast control is not suppported" ) + } + else if ( p_contrast >= 0 ) + { + vid_control.value = p_contrast; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) ) + { + if ( errno != ERANGE ) + Error( "Unable to set contrast: %s", strerror(errno) ) + else + Warning( "Given contrast value (%d) may be out-of-range", p_contrast ) + } + } + return( vid_control.value ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + struct video_picture vid_pic; + memset( &vid_pic, 0, sizeof(video_picture) ); + if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 ) + { + Error( "Failed to get picture attributes: %s", strerror(errno) ); + return( -1 ); + } + + if ( p_contrast >= 0 ) + { + vid_pic.contrast = p_contrast; + if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 ) + { + Error( "Failed to set picture attributes: %s", strerror(errno) ); + return( -1 ); + } + } + return( vid_pic.contrast ); + } +#endif // ZM_HAS_V4L1 + return( -1 ); +} + +int LocalCamera::PrimeCapture() +{ + Initialise(); + + Debug( 2, "Priming capture" ); +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + Debug( 3, "Queueing buffers" ); + for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) + { + struct v4l2_buffer vid_buf; + + memset( &vid_buf, 0, sizeof(vid_buf) ); + + vid_buf.type = v4l2_data.fmt.type; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = frame; + + if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) + Fatal( "Failed to queue buffer %d: %s", frame, strerror(errno) ); + } + v4l2_data.bufptr = NULL; + + Debug( 3, "Starting video stream" ); + //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + //enum v4l2_buf_type type = v4l2_data.fmt.type; + enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; + if ( vidioctl( vid_fd, VIDIOC_STREAMON, &type ) < 0 ) + Fatal( "Failed to start capture stream: %s", strerror(errno) ); + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ ) + { + Debug( 3, "Queueing frame %d", frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 ) + { + Error( "Capture failure for frame %d: %s", frame, strerror(errno) ); + return( -1 ); + } + } + } +#endif // ZM_HAS_V4L1 + + return( 0 ); +} + +int LocalCamera::PreCapture() +{ + Debug( 2, "Pre-capturing" ); + return( 0 ); +} + +int LocalCamera::Capture( Image &image ) +{ + Debug( 3, "Capturing" ); + static uint8_t* buffer = NULL; + static uint8_t* directbuffer = NULL; + static int capture_frame = -1; + int buffer_bytesused = 0; + + int captures_per_frame = 1; + if ( channel_count > 1 ) + captures_per_frame = config.captures_per_frame; + + + // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer + if ( channel_prime ) + { +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + static struct v4l2_buffer vid_buf; + + memset( &vid_buf, 0, sizeof(vid_buf) ); + + vid_buf.type = v4l2_data.fmt.type; + //vid_buf.memory = V4L2_MEMORY_MMAP; + vid_buf.memory = v4l2_data.reqbufs.memory; + + Debug( 3, "Capturing %d frames", captures_per_frame ); + while ( captures_per_frame ) + { + if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 ) + { + if ( errno == EIO ) + Warning( "Capture failure, possible signal loss?: %s", strerror(errno) ) + else + Error( "Unable to capture frame %d: %s", vid_buf.index, strerror(errno) ) + return( -1 ); + } + + v4l2_data.bufptr = &vid_buf; + capture_frame = v4l2_data.bufptr->index; + if ( --captures_per_frame ) + { + if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 ) + { + Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) ); + return( -1 ); + } + } + } + + Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel ); + + buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start; + buffer_bytesused = v4l2_data.bufptr->bytesused; + + if((v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) != (width * height)) { + Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height); + } + + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + Debug( 3, "Capturing %d frames", captures_per_frame ); + while ( captures_per_frame ) + { + Debug( 3, "Syncing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 ) + { + Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); + return( -1 ); + } + captures_per_frame--; + if ( captures_per_frame ) + { + Debug( 3, "Capturing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) + { + Error( "Capture failure for buffer %d (%d): %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) ); + return( -1 ); + } + } + } + capture_frame = v4l1_data.active_frame; + Debug( 3, "Captured %d for channel %d", capture_frame, channel ); + + buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame]; + } +#endif // ZM_HAS_V4L1 + } /* prime capture */ + + if(conversion_type != 0) { + + Debug( 3, "Performing format conversion" ); + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } +#if HAVE_LIBSWSCALE + if(conversion_type == 1) { + + Debug( 9, "Calling sws_scale to perform the conversion" ); + /* Use swscale to convert the image directly into the shared memory */ + avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height ); + sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize ); + } +#endif + if(conversion_type == 2) { + + Debug( 9, "Calling the conversion function" ); + /* Call the image conversion function and convert directly into the shared memory */ + (*conversion_fptr)(buffer, directbuffer, pixels); + } + else if(conversion_type == 3) { + + Debug( 9, "Decoding the JPEG image" ); + /* JPEG decoding */ + image.DecodeJpeg(buffer, buffer_bytesused, colours, subpixelorder); + } + + } else { + Debug( 3, "No format conversion performed. Assigning the image" ); + + /* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */ + image.Assign( width, height, colours, subpixelorder, buffer, imagesize); + + } + + return( 0 ); +} + +int LocalCamera::PostCapture() +{ + Debug( 2, "Post-capturing" ); + // Requeue the buffer unless we need to switch or are a duplicate camera on a channel + if ( channel_count > 1 || channel_prime ) + { +#if ZM_HAS_V4L2 + if ( v4l_version == 2 ) + { + if ( channel_count > 1 ) + { + int next_channel = (channel_index+1)%channel_count; + Debug( 3, "Switching video source to %d", channels[next_channel] ); + if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 ) + { + Error( "Failed to set camera source %d: %s", channels[next_channel], strerror(errno) ); + return( -1 ); + } + + v4l2_std_id stdId = standards[next_channel]; + if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) + { + Error( "Failed to set video format %d: %s", standards[next_channel], strerror(errno) ); + return( -1 ); + } + } + Debug( 3, "Requeueing buffer %d", v4l2_data.bufptr->index ); + if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.bufptr ) < 0 ) + { + Error( "Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno) ) + return( -1 ); + } + } +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + if ( v4l_version == 1 ) + { + if ( channel_count > 1 ) + { + Debug( 3, "Switching video source" ); + int next_channel = (channel_index+1)%channel_count; + struct video_channel vid_src; + memset( &vid_src, 0, sizeof(vid_src) ); + vid_src.channel = channel; + if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 ) + { + Error( "Failed to get camera source %d: %s", channel, strerror(errno) ); + return(-1); + } + + vid_src.channel = channels[next_channel]; + vid_src.norm = standards[next_channel]; + vid_src.flags = 0; + vid_src.type = VIDEO_TYPE_CAMERA; + if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 ) + { + Error( "Failed to set camera source %d: %s", channel, strerror(errno) ); + return( -1 ); + } + } + Debug( 3, "Requeueing frame %d", v4l1_data.active_frame ); + if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 ) + { + Error( "Capture failure for frame %d: %s", v4l1_data.active_frame, strerror(errno) ); + return( -1 ); + } + v4l1_data.active_frame = (v4l1_data.active_frame+1)%v4l1_data.frames.frames; + } +#endif // ZM_HAS_V4L1 + } + return( 0 ); +} + +#endif // ZM_HAS_V4L diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h new file mode 100644 index 000000000..05f06fe44 --- /dev/null +++ b/src/zm_local_camera.h @@ -0,0 +1,143 @@ +// +// ZoneMinder Local Camera Class Interface, $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. +// + +#ifndef ZM_LOCAL_CAMERA_H +#define ZM_LOCAL_CAMERA_H + +#include "zm.h" +#include "zm_camera.h" +#include "zm_image.h" + +#if ZM_HAS_V4L + +#ifdef HAVE_LINUX_VIDEODEV_H +#include +#endif // HAVE_LINUX_VIDEODEV_H +#ifdef HAVE_LINUX_VIDEODEV2_H +#include +#endif // HAVE_LINUX_VIDEODEV2_H + +#include "zm_ffmpeg.h" + +// +// Class representing 'local' cameras, i.e. those which are +// directly connect to the host machine and which are accessed +// via a video interface. +// +class LocalCamera : public Camera +{ +protected: +#if ZM_HAS_V4L2 + struct V4L2MappedBuffer + { + void *start; + size_t length; + }; + + struct V4L2Data + { + v4l2_cropcap cropcap; + v4l2_crop crop; + v4l2_format fmt; + v4l2_requestbuffers reqbufs; + V4L2MappedBuffer *buffers; + v4l2_buffer *bufptr; + }; +#endif // ZM_HAS_V4L2 + +#if ZM_HAS_V4L1 + struct V4L1Data + { + int active_frame; + video_mbuf frames; + video_mmap *buffers; + unsigned char *bufptr; + }; +#endif // ZM_HAS_V4L1 + +protected: + std::string device; + int channel; + int standard; + int palette; + bool device_prime; + bool channel_prime; + int channel_index; + unsigned int extras; + + unsigned int conversion_type; /* 0 = no conversion needed, 1 = use libswscale, 2 = zm internal conversion, 3 = jpeg decoding */ + convert_fptr_t conversion_fptr; /* Pointer to conversion function used */ + + uint32_t AutoSelectFormat(int p_colours); + +protected: + static int camera_count; + static int channel_count; + static int channels[VIDEO_MAX_FRAME]; + static int standards[VIDEO_MAX_FRAME]; + static int vid_fd; + static int v4l_version; + +#if ZM_HAS_V4L2 + static V4L2Data v4l2_data; +#endif // ZM_HAS_V4L2 +#if ZM_HAS_V4L1 + static V4L1Data v4l1_data; +#endif // ZM_HAS_V4L1 + +#if HAVE_LIBSWSCALE + static AVFrame **capturePictures; + PixelFormat imagePixFormat; + PixelFormat capturePixFormat; + struct SwsContext *imgConversionContext; + AVFrame *tmpPicture; +#endif // HAVE_LIBSWSCALE + + static LocalCamera *last_camera; + +public: + LocalCamera( int p_id, const std::string &device, int p_channel, int p_format, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, unsigned int p_extras = 0); + ~LocalCamera(); + + void Initialise(); + void Terminate(); + + const std::string &Device() const { return( device ); } + + int Channel() const { return( channel ); } + int Standard() const { return( standard ); } + int Palette() const { return( palette ); } + int Extras() const { return( extras ); } + + int Brightness( int p_brightness=-1 ); + int Hue( int p_hue=-1 ); + int Colour( int p_colour=-1 ); + int Contrast( int p_contrast=-1 ); + + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); + + static bool GetCurrentSettings( const char *device, char *output, int version, bool verbose ); +}; + +#endif // ZM_HAS_V4L + +#endif // ZM_LOCAL_CAMERA_H diff --git a/src/zm_logger.cpp b/src/zm_logger.cpp new file mode 100644 index 000000000..512b6af1c --- /dev/null +++ b/src/zm_logger.cpp @@ -0,0 +1,610 @@ +/* + * ZoneMinder Logger Implementation, $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. +*/ + +#include "zm_logger.h" + +#include "zm_config.h" +#include "zm_utils.h" + +#include +#include +#include +#include +#include +#ifdef HAVE_SYSCALL_H +#include +#endif // HAVE_SYSCALL_H +#include +#include +#include + +bool Logger::smInitialised = false; +Logger *Logger::smInstance = 0; + +Logger::StringMap Logger::smCodes; +Logger::IntMap Logger::smSyslogPriorities; + +#if 0 +static void subtractTime( struct timeval * const tp1, struct timeval * const tp2 ) +{ + tp1->tv_sec -= tp2->tv_sec; + if ( tp1->tv_usec <= tp2->tv_usec ) + { + tp1->tv_sec--; + tp1->tv_usec = 1000000 - (tp2->tv_usec - tp1->tv_usec); + } + else + { + tp1->tv_usec = tp1->tv_usec - tp2->tv_usec; + } +} +#endif + +void Logger::usrHandler( int sig ) +{ + Logger *logger = fetch(); + if ( sig == SIGUSR1 ) + logger->level( logger->level()+1 ); + else if ( sig == SIGUSR2 ) + logger->level( logger->level()-1 ); + Info( "Logger - Level changed to %d", logger->level() ); +} + +Logger::Logger() : + mLevel( INFO ), + mTermLevel( NOLOG ), + mDatabaseLevel( NOLOG ), + mFileLevel( NOLOG ), + mSyslogLevel( NOLOG ), + mEffectiveLevel( NOLOG ), + //mLogPath( config.path_logs ), + //mLogFile( mLogPath+"/"+mId+".log" ), + mDbConnected( false ), + mLogFileFP( NULL ), + mHasTerm( false ), + mFlush( false ) +{ + if ( smInstance ) + { + Panic( "Attempt to create second instance of Logger class" ); + } + + if ( !smInitialised ) + { + smCodes[INFO] = "INF"; + smCodes[WARNING] = "WAR"; + smCodes[ERROR] = "ERR"; + smCodes[FATAL] = "FAT"; + smCodes[PANIC] = "PNC"; + smCodes[NOLOG] = "OFF"; + + smSyslogPriorities[INFO] = LOG_INFO; + smSyslogPriorities[WARNING] = LOG_WARNING; + smSyslogPriorities[ERROR] = LOG_ERR; + smSyslogPriorities[FATAL] = LOG_ERR; + smSyslogPriorities[PANIC] = LOG_ERR; + + char code[4] = ""; + for ( int i = DEBUG1; i <= DEBUG9; i++ ) + { + snprintf( code, sizeof(code), "DB%d", i ); + smCodes[i] = code; + smSyslogPriorities[i] = LOG_DEBUG; + } + + smInitialised = true; + } + + if ( fileno(stderr) && isatty(fileno(stderr)) ) + mHasTerm = true; +} + +Logger::~Logger() +{ + terminate(); +} + +void Logger::initialise( const std::string &id, const Options &options ) +{ + char *envPtr; + + if ( !id.empty() ) + this->id( id ); + + std::string tempLogFile; + if ( options.mLogPath.size() ) + { + mLogPath = options.mLogPath; + tempLogFile = mLogPath+"/"+mId+".log"; + } + if ( options.mLogFile.size() ) + tempLogFile = options.mLogFile; + else + tempLogFile = mLogPath+"/"+mId+".log"; + if ( (envPtr = getTargettedEnv( "LOG_FILE" )) ) + tempLogFile = envPtr; + + Level tempLevel = INFO; + Level tempTermLevel = mTermLevel; + Level tempDatabaseLevel = mDatabaseLevel; + Level tempFileLevel = mFileLevel; + Level tempSyslogLevel = mSyslogLevel; + + if ( options.mTermLevel != NOOPT ) + tempTermLevel = options.mTermLevel; + if ( options.mDatabaseLevel != NOOPT ) + tempDatabaseLevel = options.mDatabaseLevel; + else + tempDatabaseLevel = config.log_level_database >= DEBUG1 ? DEBUG9 : config.log_level_database; + if ( options.mFileLevel != NOOPT ) + tempFileLevel = options.mFileLevel; + else + tempFileLevel = config.log_level_file >= DEBUG1 ? DEBUG9 : config.log_level_file; + if ( options.mSyslogLevel != NOOPT ) + tempSyslogLevel = options.mSyslogLevel; + else + tempSyslogLevel = config.log_level_syslog >= DEBUG1 ? DEBUG9 : config.log_level_syslog; + + // Legacy + if ( (envPtr = getenv( "LOG_PRINT" )) ) + tempTermLevel = atoi(envPtr) ? DEBUG9 : NOLOG; + + if ( (envPtr = getTargettedEnv( "LOG_LEVEL" )) ) + tempLevel = atoi(envPtr); + + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_TERM" )) ) + tempTermLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_DATABASE" )) ) + tempDatabaseLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_FILE" )) ) + tempFileLevel = atoi(envPtr); + if ( (envPtr = getTargettedEnv( "LOG_LEVEL_SYSLOG" )) ) + tempSyslogLevel = atoi(envPtr); + + if ( config.log_debug ) + { + StringVector targets = split( config.log_debug_target, "|" ); + for ( unsigned int i = 0; i < targets.size(); i++ ) + { + const std::string &target = targets[i]; + if ( target == mId || target == "_"+mId || target == "_"+mIdRoot || target == "_"+mIdRoot || target == "" ) + { + if ( config.log_debug_level > NOLOG ) + { + tempLevel = config.log_debug_level; + if ( config.log_debug_file[0] ) + { + tempLogFile = config.log_debug_file; + tempFileLevel = tempLevel; + } + } + } + } + } + + logFile( tempLogFile ); + + termLevel( tempTermLevel ); + databaseLevel( tempDatabaseLevel ); + fileLevel( tempFileLevel ); + syslogLevel( tempSyslogLevel ); + + level( tempLevel ); + + mFlush = (envPtr = getenv( "LOG_FLUSH")) ? atoi( envPtr ) : false; + + //mRuntime = (envPtr = getenv( "LOG_RUNTIME")) ? atoi( envPtr ) : false; + + { + struct sigaction action; + memset( &action, 0, sizeof(action) ); + action.sa_handler = usrHandler; + action.sa_flags = SA_RESTART; + + if ( sigaction( SIGUSR1, &action, 0 ) < 0 ) + { + Fatal( "sigaction(), error = %s", strerror(errno) ); + } + if ( sigaction( SIGUSR2, &action, 0 ) < 0) + { + Fatal( "sigaction(), error = %s", strerror(errno) ); + } + } + + mInitialised = true; + + Debug( 1, "LogOpts: level=%s/%s, screen=%s, database=%s, logfile=%s->%s, syslog=%s", smCodes[mLevel].c_str(), smCodes[mEffectiveLevel].c_str(), smCodes[mTermLevel].c_str(), smCodes[mDatabaseLevel].c_str(), smCodes[mFileLevel].c_str(), mLogFile.c_str(), smCodes[mSyslogLevel].c_str() ); +} + +void Logger::terminate() +{ + Info( "Terminating Logger" ); + + if ( mFileLevel > NOLOG ) + closeFile(); + + if ( mSyslogLevel > NOLOG ) + closeSyslog(); +} + +bool Logger::boolEnv( const std::string &name, bool defaultValue ) +{ + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? atoi( envPtr ) : defaultValue ); +} + +int Logger::intEnv( const std::string &name, bool defaultValue ) +{ + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? atoi( envPtr ) : defaultValue ); +} + +std::string Logger::strEnv( const std::string &name, const std::string defaultValue ) +{ + const char *envPtr = getenv( name.c_str() ); + return( envPtr ? envPtr : defaultValue ); +} + +char *Logger::getTargettedEnv( const std::string &name ) +{ + char *envPtr = NULL; + std::string envName; + + envName = name+"_"+mId; + envPtr = getenv( envName.c_str() ); + if ( !envPtr && mId != mIdRoot ) + { + envName = name+"_"+mIdRoot; + envPtr = getenv( envName.c_str() ); + } + if ( !envPtr ) + envPtr = getenv( name.c_str() ); + return( envPtr ); +} + +const std::string &Logger::id( const std::string &id ) +{ + std::string tempId = id; + + size_t pos; + // Remove whitespace + while ( (pos = tempId.find_first_of( " \t" )) != std::string::npos ) + { + tempId.replace( pos, 1, "" ); + } + // Replace non-alphanum with underscore + while ( (pos = tempId.find_first_not_of( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" )) != std::string::npos ) + { + tempId.replace( pos, 1, "_" ); + } + if ( mId != tempId ) + { + mId = tempId; + pos = mId.find( '_' ); + if ( pos != std::string::npos ) + { + mIdRoot = mId.substr( 0, pos ); + if ( ++pos < mId.size() ) + mIdArgs = mId.substr( pos ); + } + } + return( mId ); +} + +Logger::Level Logger::level( Logger::Level level ) +{ + if ( level > NOOPT ) + { + level = limit(level); + if ( mLevel != level ) + mLevel = level; + + mEffectiveLevel = NOLOG; + if ( mTermLevel > mEffectiveLevel ) + mEffectiveLevel = mTermLevel; + if ( mDatabaseLevel > mEffectiveLevel ) + mEffectiveLevel = mDatabaseLevel; + if ( mFileLevel > mEffectiveLevel ) + mEffectiveLevel = mFileLevel; + if ( mSyslogLevel > mEffectiveLevel ) + mEffectiveLevel = mSyslogLevel; + if ( mEffectiveLevel > mLevel) + mEffectiveLevel = mLevel; + } + return( mLevel ); +} + +Logger::Level Logger::termLevel( Logger::Level termLevel ) +{ + if ( termLevel > NOOPT ) + { + if ( !mHasTerm ) + termLevel = NOLOG; + termLevel = limit(termLevel); + if ( mTermLevel != termLevel ) + mTermLevel = termLevel; + } + return( mTermLevel ); +} + +Logger::Level Logger::databaseLevel( Logger::Level databaseLevel ) +{ + if ( databaseLevel > NOOPT ) + { + databaseLevel = limit(databaseLevel); + if ( mDatabaseLevel != databaseLevel ) + { + if ( databaseLevel > NOLOG && mDatabaseLevel <= NOLOG ) + { + if ( !mDbConnected ) + { + if ( !mysql_init( &mDbConnection ) ) + { + Fatal( "Can't initialise database connection: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + my_bool reconnect = 1; + if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); + std::string::size_type colonIndex = staticConfig.DB_HOST.find( ":/" ); + if ( colonIndex != std::string::npos ) + { + std::string dbHost = staticConfig.DB_HOST.substr( 0, colonIndex ); + std::string dbPort = staticConfig.DB_HOST.substr( colonIndex+1 ); + if ( !mysql_real_connect( &mDbConnection, dbHost.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, atoi(dbPort.c_str()), 0, 0 ) ) + { + Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + } + else + { + if ( !mysql_real_connect( &mDbConnection, staticConfig.DB_HOST.c_str(), staticConfig.DB_USER.c_str(), staticConfig.DB_PASS.c_str(), 0, 0, 0, 0 ) ) + { + Fatal( "Can't connect to database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + } + unsigned long mysqlVersion = mysql_get_server_version( &mDbConnection ); + if ( mysqlVersion < 50019 ) + if ( mysql_options( &mDbConnection, MYSQL_OPT_RECONNECT, &reconnect ) ) + Fatal( "Can't set database auto reconnect option: %s", mysql_error( &mDbConnection ) ); + if ( mysql_select_db( &mDbConnection, staticConfig.DB_NAME.c_str() ) ) + { + Fatal( "Can't select database: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + mDbConnected = true; + } + } + mDatabaseLevel = databaseLevel; + } + } + return( mDatabaseLevel ); +} + +Logger::Level Logger::fileLevel( Logger::Level fileLevel ) +{ + if ( fileLevel > NOOPT ) + { + fileLevel = limit(fileLevel); + if ( mFileLevel != fileLevel ) + { + if ( mFileLevel > NOLOG ) + closeFile(); + mFileLevel = fileLevel; + if ( mFileLevel > NOLOG ) + openFile(); + } + } + return( mFileLevel ); +} + +Logger::Level Logger::syslogLevel( Logger::Level syslogLevel ) +{ + if ( syslogLevel > NOOPT ) + { + syslogLevel = limit(syslogLevel); + if ( mSyslogLevel != syslogLevel ) + { + if ( mSyslogLevel > NOLOG ) + closeSyslog(); + mSyslogLevel = syslogLevel; + if ( mSyslogLevel > NOLOG ) + openSyslog(); + } + } + return( mSyslogLevel ); +} + +void Logger::logFile( const std::string &logFile ) +{ + bool addLogPid = false; + std::string tempLogFile = logFile; + if ( tempLogFile[tempLogFile.length()-1] == '+' ) + { + tempLogFile.resize(tempLogFile.length()-1); + addLogPid = true; + } + if ( addLogPid ) + mLogFile = stringtf( "%s.%05d", tempLogFile.c_str(), getpid() ); + else + mLogFile = tempLogFile; +} + +void Logger::openFile() +{ + if ( mLogFile.size() && (mLogFileFP = fopen( mLogFile.c_str() ,"w" )) == (FILE *)NULL ) + { + mFileLevel = NOLOG; + Fatal( "fopen() for %s, error = %s", mLogFile.c_str(), strerror(errno) ); + } +} + +void Logger::closeFile() +{ + if ( mLogFileFP ) + { + fflush( mLogFileFP ); + if ( fclose( mLogFileFP ) < 0 ) + { + Fatal( "fclose(), error = %s",strerror(errno) ); + } + mLogFileFP = (FILE *)NULL; + } +} + +void Logger::openSyslog() +{ + (void) openlog( mId.c_str(), LOG_PID|LOG_NDELAY, LOG_LOCAL1 ); +} + +void Logger::closeSyslog() +{ + (void) closelog(); +} + +void Logger::logPrint( bool hex, const char * const file, const int line, const int level, const char *fstring, ... ) +{ + if ( level <= mEffectiveLevel ) + { + char classString[4]; + char timeString[64]; + char logString[8192]; + va_list argPtr; + struct timeval timeVal; + + if ( level < PANIC || level > DEBUG9 ) + Panic( "Invalid logger level %d", level ); + + strncpy( classString, smCodes[level].c_str(), sizeof(classString) ); + + gettimeofday( &timeVal, NULL ); + + #if 0 + if ( logRuntime ) + { + static struct timeval logStart; + + subtractTime( &timeVal, &logStart ); + + snprintf( timeString, sizeof(timeString), "%ld.%03ld", timeVal.tv_sec, timeVal.tv_usec/1000 ); + } + else + { + #endif + char *timePtr = timeString; + timePtr += strftime( timePtr, sizeof(timeString), "%x %H:%M:%S", localtime(&timeVal.tv_sec) ); + snprintf( timePtr, sizeof(timeString)-(timePtr-timeString), ".%06ld", timeVal.tv_usec ); + #if 0 + } + #endif + + pid_t tid; +#ifdef HAVE_SYSCALL + if ( (tid = syscall(SYS_gettid)) < 0 ) // Thread/Process id +#endif // HAVE_SYSCALL + tid = getpid(); // Process id + + char *logPtr = logString; + logPtr += snprintf( logPtr, sizeof(logString), "%s %s[%d].%s-%s/%d [", + timeString, + mId.c_str(), + tid, + classString, + file, + line + ); + char *syslogStart = logPtr; + + va_start( argPtr, fstring ); + if ( hex ) + { + unsigned char *data = va_arg( argPtr, unsigned char * ); + int len = va_arg( argPtr, int ); + int i; + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), "%d:", len ); + for ( i = 0; i < len; i++ ) + { + logPtr += snprintf( logPtr, sizeof(logString)-(logPtr-logString), " %02x", data[i] ); + } + } + else + { + logPtr += vsnprintf( logPtr, sizeof(logString)-(logPtr-logString), fstring, argPtr ); + } + va_end(argPtr); + char *syslogEnd = logPtr; + strncpy( logPtr, "]\n", sizeof(logString)-(logPtr-logString) ); + + if ( level <= mTermLevel ) + { + printf( "%s", logString ); + fflush( stdout ); + } + if ( level <= mFileLevel ) + { + fprintf( mLogFileFP, "%s", logString ); + if ( mFlush ) + fflush( mLogFileFP ); + } + *syslogEnd = '\0'; + if ( level <= mDatabaseLevel ) + { + char sql[ZM_SQL_MED_BUFSIZ]; + char escapedString[(strlen(syslogStart)*2)+1]; + + 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 ); + if ( mysql_query( &mDbConnection, sql ) ) + { + databaseLevel( NOLOG ); + Fatal( "Can't insert log entry: %s", mysql_error( &mDbConnection ) ); + exit( mysql_errno( &mDbConnection ) ); + } + } + if ( level <= mSyslogLevel ) + { + int priority = smSyslogPriorities[level]; + //priority |= LOG_DAEMON; + syslog( priority, "%s [%s]", classString, syslogStart ); + } + + if ( level <= FATAL ) + { + if ( level <= PANIC ) + abort(); + exit( -1 ); + } + } +} + +void logInit( const char *name, const Logger::Options &options ) +{ + if ( !Logger::smInstance ) + Logger::smInstance = new Logger(); + Logger::Options tempOptions = options; + tempOptions.mLogPath = config.path_logs; + Logger::smInstance->initialise( name, tempOptions ); +} + +void logTerm() +{ + Logger::fetch()->terminate(); +} diff --git a/src/zm_logger.h b/src/zm_logger.h new file mode 100644 index 000000000..188aed518 --- /dev/null +++ b/src/zm_logger.h @@ -0,0 +1,239 @@ +/* + * ZoneMinder Logger Interface, $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. +*/ + +#ifndef ZM_LOGGER_H +#define ZM_LOGGER_H + +#include +#include +#include +#include + +class Logger +{ +public: + enum { + NOOPT=-6, + NOLOG, + PANIC, + FATAL, + ERROR, + WARNING, + INFO, + DEBUG1, + DEBUG2, + DEBUG3, + DEBUG4, + DEBUG5, + DEBUG6, + DEBUG7, + DEBUG8, + DEBUG9 + }; + + typedef int Level; + + typedef std::map StringMap; + typedef std::map IntMap; + + class Options + { + public: + int mTermLevel; + int mDatabaseLevel; + int mFileLevel; + int mSyslogLevel; + + std::string mLogPath; + std::string mLogFile; + + public: + Options( Level termLevel=NOOPT, Level databaseLevel=NOOPT, Level fileLevel=NOOPT, Level syslogLevel=NOOPT, const std::string &logPath=".", const std::string &logFile="" ) : + mTermLevel( termLevel ), + mDatabaseLevel( databaseLevel ), + mFileLevel( fileLevel ), + mSyslogLevel( syslogLevel ), + mLogPath( logPath ), + mLogFile( logFile ) + { + } + }; + +private: + static bool smInitialised; + static Logger *smInstance; + + static StringMap smCodes; + static IntMap smSyslogPriorities; + +private: + bool mInitialised; + + std::string mId; + std::string mIdRoot; + std::string mIdArgs; + + Level mLevel; // Level that is currently in operation + Level mTermLevel; // Maximum level output via terminal + Level mDatabaseLevel; // Maximum level output via database + Level mFileLevel; // Maximum level output via file + Level mSyslogLevel; // Maximum level output via syslog + Level mEffectiveLevel; // Level optimised to take account of maxima + + bool mDbConnected; + MYSQL mDbConnection; + std::string mLogPath; + std::string mLogFile; + FILE *mLogFileFP; + + bool mHasTerm; + bool mFlush; + +private: + static void usrHandler( int sig ); + +public: + friend void logInit( const char *name, const Options &options ); + + static Logger *fetch() + { + if ( !smInstance ) + { + smInstance = new Logger(); + Options options; + smInstance->initialise( "undef", options ); + } + return( smInstance ); + } + +private: + Logger(); + ~Logger(); + +public: + void initialise( const std::string &id, const Options &options ); + void terminate(); + +private: + int limit( int level ) + { + if ( level > DEBUG9 ) + return( DEBUG9 ); + if ( level < NOLOG ) + return( NOLOG ); + return( level ); + } + + bool boolEnv( const std::string &name, bool defaultValue=false ); + int intEnv( const std::string &name, bool defaultValue=0 ); + std::string strEnv( const std::string &name, const std::string defaultValue="" ); + char *getTargettedEnv( const std::string &name ); + + void loadEnv(); + +public: + const std::string &id() const + { + return( mId ); + } + + const std::string &id( const std::string &id ); + + Level level() const + { + return( mLevel ); + } + Level level( Level=NOOPT ); + + bool debugOn() + { + return( mEffectiveLevel >= DEBUG1 ); + } + + Level termLevel( Level=NOOPT ); + Level databaseLevel( Level=NOOPT ); + Level fileLevel( Level=NOOPT ); + Level syslogLevel( Level=NOOPT ); + +private: + void logFile( const std::string &logFile ); + void openFile(); + void closeFile(); + void openSyslog(); + void closeSyslog(); + +public: + void logPrint( bool hex, const char * const file, const int line, const int level, const char *fstring, ... ); +}; + +void logInit( const char *name, const Logger::Options &options=Logger::Options() ); +void logTerm(); +inline const std::string &logId() +{ + return( Logger::fetch()->id() ); +} +inline Logger::Level logLevel() +{ + return( Logger::fetch()->level() ); +} +inline void logCapLevel( Logger::Level level ) +{ + Logger::fetch()->level( level ); +} +inline Logger::Level logDebugging() +{ + return( Logger::fetch()->debugOn() ); +} + +#define logPrintf(logLevel,params...) {\ + if ( logLevel <= Logger::fetch()->level() )\ + Logger::fetch()->logPrint( false, __FILE__, __LINE__, logLevel, ##params );\ + } + +#define logHexdump(logLevel,data,len) {\ + if ( logLevel <= Logger::fetch()->level() )\ + Logger::fetch()->logPrint( true, __FILE__, __LINE__, logLevel, "%p (%d)", data, len );\ + } + +/* Debug compiled out */ +#ifndef DBG_OFF +#define Debug(level,params...) logPrintf(level,##params) +#define Hexdump(level,data,len) logHexdump(level,data,len) +#else +#define Debug(level,params...) +#define Hexdump(level,data,len) +#endif + +/* Standard debug calls */ +#define Info(params...) logPrintf(Logger::INFO,##params) +#define Warning(params...) logPrintf(Logger::WARNING,##params) +#define Error(params...) logPrintf(Logger::ERROR,##params) +#define Fatal(params...) logPrintf(Logger::FATAL,##params) +#define Panic(params...) logPrintf(Logger::PANIC,##params) +#define Mark() Info("Mark/%s/%d",__FILE__,__LINE__) +#define Log() Info("Log") +#ifdef __GNUC__ +#define Enter(level) logPrintf(level,("Entering %s",__PRETTY_FUNCTION__)) +#define Exit(level) logPrintf(level,("Exiting %s",__PRETTY_FUNCTION__)) +#else +#define Enter(level) +#define Exit(level) +#endif + +#endif // ZM_LOGGER_H diff --git a/src/zm_mem_utils.h b/src/zm_mem_utils.h new file mode 100644 index 000000000..8ce1ceea1 --- /dev/null +++ b/src/zm_mem_utils.h @@ -0,0 +1,161 @@ +// +// ZoneMinder Memory Utilities, $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. +// + +#ifndef ZM_MEM_UTILS_H +#define ZM_MEM_UTILS_H + +#include +#include "zm.h" + +inline void* zm_mallocaligned(unsigned int reqalignment, size_t reqsize) { + uint8_t* retptr; +#if HAVE_POSIX_MEMALIGN + if(posix_memalign((void**)&retptr,reqalignment,reqsize) != 0) + return NULL; + + return retptr; +#else + uint8_t* alloc; + retptr = (uint8_t*)malloc(reqsize+reqalignment+sizeof(void*)); + + if(retptr == NULL) + return NULL; + + alloc = retptr + sizeof(void*); + + if(((long)alloc % reqalignment) != 0) + alloc = alloc + (reqalignment - ((long)alloc % reqalignment)); + + /* Store a pointer before to the start of the block, just before returned aligned memory */ + *(void**)(alloc - sizeof(void*)) = retptr; + + return alloc; +#endif +} + +inline void zm_freealigned(void* ptr) { +#if HAVE_POSIX_MEMALIGN + free(ptr); +#else + /* Start of block is stored before the block if it was allocated by zm_mallocaligned */ + free(*(void**)((uint8_t*)ptr - sizeof(void*))); +#endif +} + +inline char *mempbrk( register const char *s, const char *accept, size_t limit ) +{ + if ( limit <= 0 || !s || !accept || !*accept ) + return( 0 ); + + register unsigned int i,j; + size_t acc_len = strlen( accept ); + + for ( i = 0; i < limit; s++, i++ ) + { + for ( j = 0; j < acc_len; j++ ) + { + if ( *s == accept[j] ) + { + return( (char *)s ); + } + } + } + return( 0 ); +} + +inline char *memstr( register const char *s, const char *n, size_t limit ) +{ + if ( limit <= 0 || !s || !n ) + return( 0 ); + + if ( !*n ) + return( (char *)s ); + + register unsigned int i,j,k; + size_t n_len = strlen( n ); + + for ( i = 0; i < limit; i++, s++ ) + { + if ( *s != *n ) + continue; + j = 1; + k = 1; + while ( true ) + { + if ( k >= n_len ) + return( (char *)s ); + if ( s[j++] != n[k++] ) + break; + } + } + return( 0 ); +} + +inline size_t memspn( register const char *s, const char *accept, size_t limit ) +{ + if ( limit <= 0 || !s || !accept || !*accept ) + return( 0 ); + + register unsigned int i,j; + size_t acc_len = strlen( accept ); + + for ( i = 0; i < limit; s++, i++ ) + { + register bool found = false; + for ( j = 0; j < acc_len; j++ ) + { + if ( *s == accept[j] ) + { + found = true; + break; + } + } + if ( !found ) + { + return( i ); + } + } + return( limit ); +} + +inline size_t memcspn( register const char *s, const char *reject, size_t limit ) +{ + if ( limit <= 0 || !s || !reject ) + return( 0 ); + + if ( !*reject ) + return( limit ); + + register unsigned int i,j; + size_t rej_len = strlen( reject ); + + for ( i = 0; i < limit; s++, i++ ) + { + for ( j = 0; j < rej_len; j++ ) + { + if ( *s == reject[j] ) + { + return( i ); + } + } + } + return( limit ); +} + +#endif // ZM_MEM_UTILS_H diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp new file mode 100644 index 000000000..66225a144 --- /dev/null +++ b/src/zm_monitor.cpp @@ -0,0 +1,4232 @@ +// +// ZoneMinder Monitor Class Implementation, $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. +// + +#include +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_time.h" +#include "zm_mpeg.h" +#include "zm_signal.h" +#include "zm_monitor.h" +#if ZM_HAS_V4L +#include "zm_local_camera.h" +#endif // ZM_HAS_V4L +#include "zm_remote_camera.h" +#include "zm_remote_camera_http.h" +#if HAVE_LIBAVFORMAT +#include "zm_remote_camera_rtsp.h" +#endif // HAVE_LIBAVFORMAT +#include "zm_file_camera.h" +#if HAVE_LIBAVFORMAT +#include "zm_ffmpeg_camera.h" +#endif // HAVE_LIBAVFORMAT + +#if ZM_MEM_MAPPED +#include +#include +#else // ZM_MEM_MAPPED +#include +#include +#endif // ZM_MEM_MAPPED + +//============================================================================= +std::string trimSpaces(std::string str) +{ + // Trim Both leading and trailing spaces + size_t startpos = str.find_first_not_of(" \t"); // Find the first character position after excluding leading blank spaces + size_t endpos = str.find_last_not_of(" \t"); // Find the first character position from reverse af + + // if all spaces or empty return an empty string + if(( std::string::npos == startpos ) || ( std::string::npos == endpos)) + { + return std::string(""); + } + else + return str.substr( startpos, endpos-startpos+1 ); +} + +std::vector split(const std::string &s, char delim) { + std::vector elems; + std::stringstream ss(s); + std::string item; + while(std::getline(ss, item, delim)) { + elems.push_back(trimSpaces(item)); + } + return elems; +} +//============================================================================= + + + +Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) +{ + strncpy( name, p_name, sizeof(name) ); + +#if ZM_MEM_MAPPED + map_fd = -1; + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); +#else // ZM_MEM_MAPPED + shm_id = 0; +#endif // ZM_MEM_MAPPED + mem_size = 0; + mem_ptr = 0; + + last_event = 0; + last_state = IDLE; + + last_connect_time = 0; + connected = false; +} + +Monitor::MonitorLink::~MonitorLink() +{ + disconnect(); +} + +bool Monitor::MonitorLink::connect() +{ + if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) + { + last_connect_time = time( 0 ); + + mem_size = sizeof(SharedData) + sizeof(TriggerData); + + Debug( 1, "link.mem.size=%d", mem_size ); +#if ZM_MEM_MAPPED + map_fd = open( mem_file, O_RDWR, (mode_t)0600 ); + if ( map_fd < 0 ) + { + Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + + struct stat map_stat; + if ( fstat( map_fd, &map_stat ) < 0 ) + { + Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + + if ( map_stat.st_size == 0 ) + { + Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + else if ( map_stat.st_size < mem_size ) + { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + disconnect(); + return( false ); + } + + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) + { + Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) ); + disconnect(); + return( false ); + } +#else // ZM_MEM_MAPPED + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); + if ( shm_id < 0 ) + { + Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } +#endif // ZM_MEM_MAPPED + + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + + if ( !shared_data->valid ) + { + Debug( 3, "Linked memory not initialised by capture daemon" ); + disconnect(); + return( false ); + } + + last_state = shared_data->state; + last_event = shared_data->last_event; + connected = true; + + return( true ); + } + return( false ); +} + +bool Monitor::MonitorLink::disconnect() +{ + if ( connected ) + { + connected = false; + +#if ZM_MEM_MAPPED + if ( mem_ptr > 0 ) + { + msync( mem_ptr, mem_size, MS_ASYNC ); + munmap( mem_ptr, mem_size ); + } + if ( map_fd >= 0 ) + close( map_fd ); + + map_fd = -1; +#else // ZM_MEM_MAPPED + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } + + shm_id = 0; + + if ( shm_data.shm_nattch <= 1 ) + { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } + } + + if ( shmdt( mem_ptr ) < 0 ) + { + Debug( 3, "Can't shmdt: %s", strerror(errno) ); + return( false ); + } + +#endif // ZM_MEM_MAPPED + mem_size = 0; + mem_ptr = 0; + } + return( true ); +} + +bool Monitor::MonitorLink::isAlarmed() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM ); +} + +bool Monitor::MonitorLink::inAlarm() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM || shared_data->state == ALERT ); +} + +bool Monitor::MonitorLink::hasAlarmed() +{ + if ( shared_data->state == ALARM ) + { + return( true ); + } + else if( shared_data->last_event != (unsigned int)last_event ) + { + last_event = shared_data->last_event; + return( true ); + } + return( false ); +} + +Monitor::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, + const char *p_event_prefix, + const char *p_label_format, + const Coord &p_label_coord, + 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_capture_delay, + int p_alarm_capture_delay, + int p_fps_report_interval, + int p_ref_blend_perc, + bool p_track_motion, + Rgb p_signal_check_colour, + Purpose p_purpose, + int p_n_zones, + Zone *p_zones[], + std::string p_sPlugins, + int p_DoNativeMotDet +) : id( p_id ), + function( (Function)p_function ), + enabled( p_enabled ), + width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), + height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), + orientation( (Orientation)p_orientation ), + deinterlacing( p_deinterlacing ), + label_coord( p_label_coord ), + image_buffer_count( p_image_buffer_count ), + warmup_count( p_warmup_count ), + pre_event_count( p_pre_event_count ), + post_event_count( p_post_event_count ), + stream_replay_buffer( p_stream_replay_buffer ), + section_length( p_section_length ), + frame_skip( p_frame_skip ), + capture_delay( p_capture_delay ), + alarm_capture_delay( p_alarm_capture_delay ), + alarm_frame_count( p_alarm_frame_count ), + fps_report_interval( p_fps_report_interval ), + ref_blend_perc( p_ref_blend_perc ), + track_motion( p_track_motion ), + signal_check_colour( p_signal_check_colour ), + delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ), + ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ), + purpose( p_purpose ), + camera( p_camera ), + n_zones( p_n_zones ), + zones( p_zones ), + iDoNativeMotDet(p_DoNativeMotDet) +{ + strncpy( name, p_name, sizeof(name) ); + + strncpy( event_prefix, p_event_prefix, sizeof(event_prefix) ); + strncpy( label_format, p_label_format, sizeof(label_format) ); + + // Change \n to actual line feeds + char *token_ptr = label_format; + const char *token_string = "\n"; + while( ( token_ptr = strstr( token_ptr, token_string ) ) ) + { + if ( *(token_ptr+1) ) + { + *token_ptr = '\n'; + token_ptr++; + strcpy( token_ptr, token_ptr+1 ); + } + else + { + *token_ptr = '\0'; + break; + } + } + + fps = 0.0; + event_count = 0; + image_count = 0; + ready_count = warmup_count; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; + + if ( alarm_frame_count < 1 ) + alarm_frame_count = 1; + else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) + alarm_frame_count = MAX_PRE_ALARM_FRAMES; + + auto_resume_time = 0; + + if ( strcmp( config.event_close_mode, "time" ) == 0 ) + event_close_mode = CLOSE_TIME; + else if ( strcmp( config.event_close_mode, "alarm" ) == 0 ) + event_close_mode = CLOSE_ALARM; + else + event_close_mode = CLOSE_IDLE; + + Debug( 1, "monitor purpose=%d", purpose ); + + mem_size = sizeof(SharedData) + + sizeof(TriggerData) + + (image_buffer_count*sizeof(struct timeval)) + + (image_buffer_count*camera->ImageSize()) + + 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */ + + Debug( 1, "mem.size=%d", mem_size ); +#if ZM_MEM_MAPPED + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); + map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); + if ( map_fd < 0 ) + Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + struct stat map_stat; + if ( fstat( map_fd, &map_stat ) < 0 ) + Fatal( "Can't stat memory map file %s: %s", mem_file, strerror(errno) ); + if ( map_stat.st_size != mem_size && purpose == CAPTURE ) + { + // Allocate the size + if ( ftruncate( map_fd, mem_size ) < 0 ) + Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); + } + else if ( map_stat.st_size != mem_size ) + { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + } + + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) + if ( errno == EAGAIN ) + { + Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + } + if ( mem_ptr == MAP_FAILED ) + Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); +#else // ZM_MEM_MAPPED + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); + if ( shm_id < 0 ) + { + Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); + exit( -1 ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Error( "Can't shmat: %s", strerror(errno)); + exit( -1 ); + } +#endif // ZM_MEM_MAPPED + + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData)); + unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); + + if(((unsigned long)shared_images % 16) != 0) { + /* Align images buffer to nearest 16 byte boundary */ + Debug(3,"Aligning shared memory images to the next 16 byte boundary"); + shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16))); + } + + //======================================================================================== + // Get from string with plugins names particular names. + m_sPluginNames = split(p_sPlugins, ';'); + + //======================================================================================== + + + if ( purpose == CAPTURE ) + { + memset( mem_ptr, 0, mem_size ); + shared_data->size = sizeof(SharedData); + shared_data->active = enabled; + shared_data->signal = false; + shared_data->state = IDLE; + shared_data->last_write_index = image_buffer_count; + shared_data->last_read_index = image_buffer_count; + shared_data->last_write_time = 0; + shared_data->last_event = 0; + shared_data->action = (Action)0; + shared_data->brightness = -1; + shared_data->hue = -1; + shared_data->colour = -1; + shared_data->contrast = -1; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + shared_data->format = camera->SubpixelOrder(); + shared_data->imagesize = camera->ImageSize(); + trigger_data->size = sizeof(TriggerData); + trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_score = 0; + trigger_data->trigger_cause[0] = 0; + trigger_data->trigger_text[0] = 0; + trigger_data->trigger_showtext[0] = 0; + shared_data->valid = true; + } + else if ( purpose == ANALYSIS ) + { + shared_data->state = IDLE; + shared_data->last_read_time = 0; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + //======================================================================================== + Info("In the constructor of Monitor class with ID=%d:", p_id); + if (config.load_plugins) + { + Info("Load plugins from the directory %s ... ", config.path_plugins); + std::string sPluginExt = std::string(config.plugin_extension); + ThePluginManager.setPluginExt(sPluginExt); + for (std::vector::iterator it = m_sPluginNames.begin() ; it < m_sPluginNames.end(); it++ ) + { + std::string sFullPluginPath = join_paths(config.path_plugins, *it + config.plugin_extension); + Info("Plugin path %s", sFullPluginPath.c_str()); + ThePluginManager.loadPlugin(sFullPluginPath); + } + +// int count_plugins = ThePluginManager.findPlugins(config.path_plugins); +// Info("Number of found plugins is %d", count_plugins); +// if (count_plugins > 0) +// { + std::string sPluginsConfig = std::string(config.plugins_config_path); + Info("Configure plugins with \'%s\' config file.", config.plugins_config_path); + ThePluginManager.configurePlugins(sPluginsConfig); +// } + + } + //======================================================================================== + + } + + if ( !shared_data->valid ) + { + if ( purpose != QUERY ) + { + Error( "Shared data not initialised by capture daemon" ); + exit( -1 ); + } + else + { + Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" ); + } + } + + image_buffer = new Snapshot[image_buffer_count]; + for ( int i = 0; i < image_buffer_count; i++ ) + { + image_buffer[i].timestamp = &(shared_timestamps[i]); + image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); + image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + } + if ( (deinterlacing & 0xff) == 4) + { + /* Four field motion adaptive deinterlacing in use */ + /* Allocate a buffer for the next image */ + next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); + next_buffer.timestamp = new struct timeval; + } + if ( !n_zones ) + { + n_zones = 1; + zones = new Zone *[1]; + Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) }; + zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); + } + start_time = last_fps_time = time( 0 ); + + event = 0; + + Debug( 1, "Monitor %s has function %d", name, function ); + Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() ); + Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, track_motion ); + + if ( purpose == ANALYSIS ) + { + static char path[PATH_MAX]; + + strncpy( path, config.dir_events, sizeof(path) ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + } + + snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); + + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + char temp_path[PATH_MAX]; + snprintf( temp_path, sizeof(temp_path), "%d", id ); + if ( chdir( config.dir_events ) < 0 ) + Fatal( "Can't change directory to '%s': %s", config.dir_events, strerror(errno) ); + if ( symlink( temp_path, name ) < 0 ) + Fatal( "Can't symlink '%s' to '%s': %s", temp_path, name, strerror(errno) ); + if ( chdir( ".." ) < 0 ) + Fatal( "Can't change to parent directory: %s", strerror(errno) ); + } + + while( shared_data->last_write_index == (unsigned int)image_buffer_count + && shared_data->last_write_time == 0) + { + Warning( "Waiting for capture daemon" ); + sleep( 1 ); + } + ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); + + n_linked_monitors = 0; + linked_monitors = 0; + ReloadLinkedMonitors( p_linked_monitors ); + } +} + +Monitor::~Monitor() +{ + if ( event ) + Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); + closeEvent(); + + if ( (deinterlacing & 0xff) == 4) + { + delete next_buffer.image; + delete next_buffer.timestamp; + } + for ( int i = 0; i < image_buffer_count; i++ ) + { + delete image_buffer[i].image; + } + delete[] image_buffer; + + for ( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + + delete camera; + + if ( purpose == ANALYSIS ) + { + shared_data->state = state = IDLE; + shared_data->last_read_index = image_buffer_count; + shared_data->last_read_time = 0; + } + else if ( purpose == CAPTURE ) + { + shared_data->valid = false; + memset( mem_ptr, 0, mem_size ); + } + +#if ZM_MEM_MAPPED + if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 ) + Error( "Can't msync: %s", strerror(errno) ); + if ( munmap( mem_ptr, mem_size ) < 0 ) + Fatal( "Can't munmap: %s", strerror(errno) ); + close( map_fd ); +#else // ZM_MEM_MAPPED + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + if ( shm_data.shm_nattch <= 1 ) + { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) + { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + } +#endif // ZM_MEM_MAPPED +} + +void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) +{ + for ( int i = 0; i < n_zones; i++ ) + delete zones[i]; + delete[] zones; + n_zones = p_n_zones; + zones = p_zones; +} + +Monitor::State Monitor::GetState() const +{ + return( (State)shared_data->state ); +} + +int Monitor::GetImage( int index, int scale ) const +{ + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } + + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; + Image snap_image( *(snap->image) ); + + if ( scale != ZM_SCALE_BASE ) + { + snap_image.Scale( scale ); + } + + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + if ( !config.timestamp_on_capture ) + { + TimestampImage( &snap_image, snap->timestamp ); + } + snap_image.WriteJpeg( filename ); + } + else + { + Error( "Unable to generate image, no images in buffer" ); + } + return( 0 ); +} + +struct timeval Monitor::GetTimestamp( int index ) const +{ + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } + + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; + + return( *(snap->timestamp) ); + } + else + { + static struct timeval null_tv = { 0, 0 }; + + return( null_tv ); + } +} + +unsigned int Monitor::GetLastReadIndex() const +{ + return( shared_data->last_read_index!=(unsigned int)image_buffer_count?shared_data->last_read_index:-1 ); +} + +unsigned int Monitor::GetLastWriteIndex() const +{ + return( shared_data->last_write_index!=(unsigned int)image_buffer_count?shared_data->last_write_index:-1 ); +} + +unsigned int Monitor::GetLastEvent() const +{ + return( shared_data->last_event ); +} + +double Monitor::GetFPS() const +{ + int index1 = shared_data->last_write_index; + if ( index1 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap1 = &image_buffer[index1]; + if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) + { + return( 0.0 ); + } + struct timeval time1 = *snap1->timestamp; + + int image_count = image_buffer_count; + int index2 = (index1+1)%image_buffer_count; + if ( index2 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap2 = &image_buffer[index2]; + while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) + { + if ( index1 == index2 ) + { + return( 0.0 ); + } + index2 = (index2+1)%image_buffer_count; + snap2 = &image_buffer[index2]; + image_count--; + } + struct timeval time2 = *snap2->timestamp; + + double time_diff = tvDiffSec( time2, time1 ); + + double curr_fps = image_count/time_diff; + + if ( curr_fps < 0.0 ) + { + //Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); + return( 0.0 ); + } + return( curr_fps ); +} + +void Monitor::ForceAlarmOn( int force_score, const char *force_cause, const char *force_text ) +{ + trigger_data->trigger_state = TRIGGER_ON; + trigger_data->trigger_score = force_score; + strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); + strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); +} + +void Monitor::ForceAlarmOff() +{ + trigger_data->trigger_state = TRIGGER_OFF; +} + +void Monitor::CancelForced() +{ + trigger_data->trigger_state = TRIGGER_CANCEL; +} + +void Monitor::actionReload() +{ + shared_data->action |= RELOAD; +} + +void Monitor::actionEnable() +{ + shared_data->action |= RELOAD; + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +void Monitor::actionDisable() +{ + shared_data->action |= RELOAD; + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +void Monitor::actionSuspend() +{ + shared_data->action |= SUSPEND; +} + +void Monitor::actionResume() +{ + shared_data->action |= RESUME; +} + +int Monitor::actionBrightness( int p_brightness ) +{ + if ( purpose != CAPTURE ) + { + if ( p_brightness >= 0 ) + { + shared_data->brightness = p_brightness; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set brightness" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get brightness" ); + return( -1 ); + } + } + } + return( shared_data->brightness ); + } + return( camera->Brightness( p_brightness ) ); +} + +int Monitor::actionContrast( int p_contrast ) +{ + if ( purpose != CAPTURE ) + { + if ( p_contrast >= 0 ) + { + shared_data->contrast = p_contrast; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set contrast" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get contrast" ); + return( -1 ); + } + } + } + return( shared_data->contrast ); + } + return( camera->Contrast( p_contrast ) ); +} + +int Monitor::actionHue( int p_hue ) +{ + if ( purpose != CAPTURE ) + { + if ( p_hue >= 0 ) + { + shared_data->hue = p_hue; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set hue" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get hue" ); + return( -1 ); + } + } + } + return( shared_data->hue ); + } + return( camera->Hue( p_hue ) ); +} + +int Monitor::actionColour( int p_colour ) +{ + if ( purpose != CAPTURE ) + { + if ( p_colour >= 0 ) + { + shared_data->colour = p_colour; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set colour" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get colour" ); + return( -1 ); + } + } + } + return( shared_data->colour ); + } + return( camera->Colour( p_colour ) ); +} + +void Monitor::DumpZoneImage( const char *zone_string ) +{ + int exclude_id = 0; + int extra_colour = 0; + Polygon extra_zone; + + if ( zone_string ) + { + if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) + { + Error( "Failed to parse zone string, ignoring" ); + } + } + + int index = shared_data->last_write_index; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + Image zone_image( *snap_image ); + if(zone_image.Colours() == ZM_COLOUR_GRAY8) { + zone_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + } + + for( int i = 0; i < n_zones; i++ ) + { + if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zones[i]->Id() == exclude_id ) + continue; + + Rgb colour; + if ( exclude_id && !extra_zone.getNumCoords() && zones[i]->Id() == exclude_id ) + { + colour = extra_colour; + } + else + { + if ( zones[i]->IsActive() ) + { + colour = RGB_RED; + } + else if ( zones[i]->IsInclusive() ) + { + colour = RGB_ORANGE; + } + else if ( zones[i]->IsExclusive() ) + { + colour = RGB_PURPLE; + } + else if ( zones[i]->IsPreclusive() ) + { + colour = RGB_BLUE; + } + else + { + colour = RGB_WHITE; + } + } + zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); + zone_image.Outline( colour, zones[i]->GetPolygon() ); + } + + if ( extra_zone.getNumCoords() ) + { + zone_image.Fill( extra_colour, 2, extra_zone ); + zone_image.Outline( extra_colour, extra_zone ); + } + + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); + zone_image.WriteJpeg( filename ); +} + +void Monitor::DumpImage( Image *dump_image ) const +{ + if ( image_count && !(image_count%10) ) + { + static char filename[PATH_MAX]; + static char new_filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + snprintf( new_filename, sizeof(new_filename), "Monitor%d-new.jpg", id ); + dump_image->WriteJpeg( new_filename ); + rename( new_filename, filename ); + } +} + +bool Monitor::CheckSignal( const Image *image ) +{ + static bool static_undef = true; + /* RGB24 colors */ + static uint8_t red_val; + static uint8_t green_val; + static uint8_t blue_val; + static uint8_t grayscale_val; /* 8bit grayscale color */ + static Rgb colour_val; /* RGB32 color */ + static int usedsubpixorder; + + if ( config.signal_check_points > 0 ) + { + if ( static_undef ) + { + static_undef = false; + usedsubpixorder = camera->SubpixelOrder(); + colour_val = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ + colour_val = rgb_convert(colour_val, usedsubpixorder); + red_val = RED_VAL_BGRA(signal_check_colour); + green_val = GREEN_VAL_BGRA(signal_check_colour); + blue_val = BLUE_VAL_BGRA(signal_check_colour); + grayscale_val = signal_check_colour & 0xff; /* Clear all bytes but lowest byte */ + } + + const uint8_t *buffer = image->Buffer(); + int pixels = image->Pixels(); + int width = image->Width(); + int colours = image->Colours(); + + int index = 0; + for ( int i = 0; i < config.signal_check_points; i++ ) + { + while( true ) + { + index = (int)(((long long)rand()*(long long)(pixels-1))/RAND_MAX); + if ( !config.timestamp_on_capture || !label_format[0] ) + break; + // Avoid sampling the rows with timestamp in + if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width ) + break; + } + + if(colours == ZM_COLOUR_GRAY8) { + if ( *(buffer+index) != grayscale_val ) + return true; + + } else if(colours == ZM_COLOUR_RGB24) { + const uint8_t *ptr = buffer+(index*colours); + + if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) { + if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) ) + return true; + } else { + /* Assume RGB */ + if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) ) + return true; + } + + } else if(colours == ZM_COLOUR_RGB32) { + if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) { + if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) ) + return true; + } else { + /* Assume RGBA or BGRA */ + if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) ) + return true; + } + } + + } + return( false ); + } + return( true ); +} + +bool Monitor::Analyse() +{ + if ( shared_data->last_read_index == shared_data->last_write_index ) + { + return( false ); + } + + struct timeval now; + gettimeofday( &now, NULL ); + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); + Info( "%s: %d - Processing at %.2f fps", name, image_count, fps ); + last_fps_time = now.tv_sec; + } + + int index; + if ( config.opt_adaptive_skip ) + { + int read_margin = shared_data->last_read_index - shared_data->last_write_index; + if ( read_margin < 0 ) read_margin += image_buffer_count; + + int step = 1; + if ( read_margin > 0 ) + { + step = (9*image_buffer_count)/(5*read_margin); + } + + int pending_frames = shared_data->last_write_index - shared_data->last_read_index; + if ( pending_frames < 0 ) pending_frames += image_buffer_count; + + Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); + if ( step <= pending_frames ) + { + index = (shared_data->last_read_index+step)%image_buffer_count; + } + else + { + if ( pending_frames ) + { + Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); + } + index = shared_data->last_write_index%image_buffer_count; + } + } + else + { + index = shared_data->last_write_index%image_buffer_count; + } + + Snapshot *snap = &image_buffer[index]; + struct timeval *timestamp = snap->timestamp; + Image *snap_image = snap->image; + + if ( shared_data->action ) + { + if ( shared_data->action & RELOAD ) + { + Info( "Received reload indication at count %d", image_count ); + shared_data->action &= ~RELOAD; + Reload(); + } + if ( shared_data->action & SUSPEND ) + { + if ( Active() ) + { + Info( "Received suspend indication at count %d", image_count ); + shared_data->active = false; + //closeEvent(); + } + if ( config.max_suspend_time ) + { + auto_resume_time = now.tv_sec + config.max_suspend_time; + } + shared_data->action &= ~SUSPEND; + } + if ( shared_data->action & RESUME ) + { + if ( Enabled() && !Active() ) + { + Info( "Received resume indication at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + shared_data->alarm_x = shared_data->alarm_y = -1; + } + shared_data->action &= ~RESUME; + } + } + if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) + { + Info( "Auto resuming at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + auto_resume_time = 0; + } + + static bool static_undef = true; + static struct timeval **timestamps; + static Image **images; + static int last_section_mod = 0; + static bool last_signal; + + if ( static_undef ) + { + static_undef = false; + timestamps = new struct timeval *[pre_event_count]; + images = new Image *[pre_event_count]; + last_signal = shared_data->signal; + } + + if ( Enabled() ) + { + bool signal = shared_data->signal; + bool signal_change = (signal != last_signal); + if ( trigger_data->trigger_state != TRIGGER_OFF ) + { + unsigned int score = 0; + if ( Ready() ) + { + std::string cause; + Event::StringSetMap noteSetMap; + + if ( trigger_data->trigger_state == TRIGGER_ON ) + { + score += trigger_data->trigger_score; + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += trigger_data->trigger_cause; + } + Event::StringSet noteSet; + noteSet.insert( trigger_data->trigger_text ); + noteSetMap[trigger_data->trigger_cause] = noteSet; + } + if ( signal_change ) + { + const char *signalText; + if ( !signal ) + signalText = "Lost"; + else + { + signalText = "Reacquired"; + score += 100; + } + Warning( "%s: %s", SIGNAL_CAUSE, signalText ); + if ( event && !signal ) + { + Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += SIGNAL_CAUSE; + } + Event::StringSet noteSet; + noteSet.insert( signalText ); + noteSetMap[SIGNAL_CAUSE] = noteSet; + shared_data->state = state = IDLE; + shared_data->active = signal; + ref_image = *snap_image; + } + else if ( signal && Active() && (function == MODECT || function == MOCORD) ) + { + if ((config.turnoff_native_analysis && !config.load_plugins) || (!config.turnoff_native_analysis && (iDoNativeMotDet || (!iDoNativeMotDet && !config.load_plugins))) ) + + { + Event::StringSet zoneSet; + int motion_score = DetectMotion( *snap_image, zoneSet ); + //int motion_score = DetectBlack( *snap_image, zoneSet ); + if ( motion_score ) + { + if ( !event ) + { + score += motion_score; + if ( cause.length() ) + cause += ", "; + cause += MOTION_CAUSE; + } + else + { + score += motion_score; + } + noteSetMap[MOTION_CAUSE] = zoneSet; + + } + } + //==================================================================== + else + { + + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + zones[n_zone]->ResetStats(); + } + } + + if (config.load_plugins) + { + std::string det_cause; // detection cause to fill in plugin's detectors + score += ThePluginManager.getImageAnalyser().DoDetection(*snap_image, zones, n_zones, noteSetMap, det_cause); + if (!event) + { + if (det_cause.length()) + { + if (cause.length()) + cause += ", "; + cause += det_cause; + } + + } + } + //==================================================================== + + shared_data->active = signal; + } + if ( (!signal_change && signal) && n_linked_monitors > 0 ) + { + bool first_link = true; + Event::StringSet noteSet; + for ( int i = 0; i < n_linked_monitors; i++ ) + { + if ( linked_monitors[i]->isConnected() ) + { + if ( linked_monitors[i]->hasAlarmed() ) + { + if ( !event ) + { + if ( first_link ) + { + if ( cause.length() ) + cause += ", "; + cause += LINKED_CAUSE; + first_link = false; + } + } + noteSet.insert( linked_monitors[i]->Name() ); + score += 50; + } + } + else + { + linked_monitors[i]->connect(); + } + } + if ( noteSet.size() > 0 ) + noteSetMap[LINKED_CAUSE] = noteSet; + } + if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) + { + if ( event ) + { + int section_mod = timestamp->tv_sec%section_length; + if ( section_mod < last_section_mod ) + { + if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) + { + if ( state == TAPE ) + { + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, section end", name, image_count, event->Id() ) + } + else + Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + } + else + { + last_section_mod = section_mod; + } + } + if ( !event ) + { + + // Create event + event = new Event( this, *timestamp, "Continuous", noteSetMap ); + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); + + /* To prevent cancelling out an existing alert\prealarm\alarm state */ + if ( state == IDLE ) + { + shared_data->state = state = TAPE; + } + + //if ( config.overlap_timed_events ) + if ( false ) + { + int pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + int pre_event_images = pre_event_count; + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index+1)%image_buffer_count; + pre_event_images--; + } + + if ( pre_event_images ) + { + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_images, images, timestamps ); + } + } + } + } + if ( score ) + { + if ( (state == IDLE || state == TAPE || state == PREALARM ) ) + { + if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) + { + Info( "%s: %03d - Gone into alarm state", name, image_count ); + shared_data->state = state = ALARM; + if ( signal_change || (function != MOCORD && state != ALERT) ) + { + int pre_index; + if ( alarm_frame_count > 1 ) + pre_index = ((index+image_buffer_count)-((alarm_frame_count-1)+pre_event_count))%image_buffer_count; + else + pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + + int pre_event_images = pre_event_count; + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index+1)%image_buffer_count; + pre_event_images--; + } + + event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); + + if ( pre_event_images ) + { + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_images, images, timestamps ); + } + if ( alarm_frame_count ) + { + event->SavePreAlarmFrames(); + } + } + } + else if ( state != PREALARM ) + { + Info( "%s: %03d - Gone into prealarm state", name, image_count ); + shared_data->state = state = PREALARM; + } + } + else if ( state == ALERT ) + { + Info( "%s: %03d - Gone back into alarm state", name, image_count ); + shared_data->state = state = ALARM; + } + last_alarm_count = image_count; + } + else + { + if ( state == ALARM ) + { + Info( "%s: %03d - Gone into alert state", name, image_count ); + shared_data->state = state = ALERT; + } + else if ( state == ALERT ) + { + if ( image_count-last_alarm_count > post_event_count ) + { + Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); + //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) + if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) + { + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); + closeEvent(); + } + else + { + shared_data->state = state = TAPE; + } + } + } + if ( state == PREALARM ) + { + if ( function != MOCORD ) + { + shared_data->state = state = IDLE; + } + else + { + shared_data->state = state = TAPE; + } + } + if ( Event::PreAlarmCount() ) + Event::EmptyPreAlarmFrames(); + } + if ( state != IDLE ) + { + if ( state == PREALARM || state == ALARM ) + { + if ( config.create_analysis_images ) + { + bool got_anal_image = false; + Image alarm_image( *snap_image ); + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( zones[i]->AlarmImage() ) + { + alarm_image.Overlay( *(zones[i]->AlarmImage()) ); + got_anal_image = true; + } + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( got_anal_image ) + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); + else + event->AddFrame( snap_image, *timestamp, score, &alarm_image ); + } + else + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + } + else + { + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + if ( event && noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == ALERT ) + { + event->AddFrame( snap_image, *timestamp ); + if ( noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == TAPE ) + { + if ( !(image_count%(frame_skip+1)) ) + { + if ( config.bulk_frame_interval > 1 ) + { + event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); + } + } + } + } + } + } + else + { + if ( event ) + { + Info( "%s: %03d - Closing event %d, trigger off", name, image_count, event->Id() ); + closeEvent(); + } + shared_data->state = state = IDLE; + last_section_mod = 0; + } + if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) && (config.blend_alarmed_images || state != ALARM) ) + { + ref_image.Blend( *snap_image, ref_blend_perc ); + } + last_signal = signal; + } + + shared_data->last_read_index = index%image_buffer_count; + //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; + shared_data->last_read_time = now.tv_sec; + image_count++; + + return( true ); +} + +void Monitor::Reload() +{ + Debug( 1, "Reloading monitor %s", name ); + + if ( event ) + Info( "%s: %03d - Closing event %d, reloading", name, image_count, event->Id() ); + + closeEvent(); + + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet, SignalCheckColour 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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors != 1 ) + { + Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); + return; + } + + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + int index = 0; + function = (Function)atoi(dbrow[index++]); + enabled = atoi(dbrow[index++]); + const char *p_linked_monitors = dbrow[index++]; + strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); + strncpy( label_format, dbrow[index++], sizeof(label_format) ); + label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; + warmup_count = atoi(dbrow[index++]); + pre_event_count = atoi(dbrow[index++]); + post_event_count = atoi(dbrow[index++]); + alarm_frame_count = atoi(dbrow[index++]); + section_length = atoi(dbrow[index++]); + frame_skip = atoi(dbrow[index++]); + capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + fps_report_interval = atoi(dbrow[index++]); + ref_blend_perc = atoi(dbrow[index++]); + track_motion = atoi(dbrow[index++]); + + //============================================================================ + std::string plugins = dbrow[index]; index++; + m_sPluginNames = split(plugins ,';'); + iDoNativeMotDet = atoi(dbrow[index++]); + //============================================================================ + + + if ( dbrow[index][0] == '#' ) + signal_check_colour = strtol(dbrow[index]+1,0,16); + else + signal_check_colour = strtol(dbrow[index],0,16); + index++; + + shared_data->state = state = IDLE; + shared_data->alarm_x = shared_data->alarm_y = -1; + if ( enabled ) + shared_data->active = true; + ready_count = image_count+warmup_count; + + ReloadLinkedMonitors( p_linked_monitors ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + mysql_free_result( result ); + + ReloadZones(); +} + +void Monitor::ReloadZones() +{ + Debug( 1, "Reloading zones for monitor %s", name ); + for( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + zones = 0; + n_zones = Zone::Load( this, zones ); + //DumpZoneImage(); +} + +void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) +{ + Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); + if ( n_linked_monitors ) + { + for( int i = 0; i < n_linked_monitors; i++ ) + { + delete linked_monitors[i]; + } + delete[] linked_monitors; + linked_monitors = 0; + } + + n_linked_monitors = 0; + if ( p_linked_monitors ) + { + int n_link_ids = 0; + unsigned int link_ids[256]; + + char link_id_str[8]; + char *dest_ptr = link_id_str; + const char *src_ptr = p_linked_monitors; + while( 1 ) + { + dest_ptr = link_id_str; + while( *src_ptr >= '0' && *src_ptr <= '9' ) + { + if ( (dest_ptr-link_id_str) < (unsigned int)(sizeof(link_id_str)-1) ) + { + *dest_ptr++ = *src_ptr++; + } + else + { + break; + } + } + // Add the link monitor + if ( dest_ptr != link_id_str ) + { + *dest_ptr = '\0'; + unsigned int link_id = atoi(link_id_str); + if ( link_id > 0 && link_id != id) + { + Debug( 3, "Found linked monitor id %d", link_id ); + int j; + for ( j = 0; j < n_link_ids; j++ ) + { + if ( link_ids[j] == link_id ) + break; + } + if ( j == n_link_ids ) // Not already found + { + link_ids[n_link_ids++] = link_id; + } + } + } + if ( !*src_ptr ) + break; + while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) + src_ptr++; + if ( !*src_ptr ) + break; + } + if ( n_link_ids > 0 ) + { + Debug( 1, "Linking to %d monitors", n_link_ids ); + linked_monitors = new MonitorLink *[n_link_ids]; + int count = 0; + for ( int i = 0; i < n_link_ids; i++ ) + { + Debug( 1, "Checking linked monitor %d", link_ids[i] ); + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors == 1 ) + { + MYSQL_ROW dbrow = mysql_fetch_row( result ); + Debug( 1, "Linking to monitor %d", link_ids[i] ); + linked_monitors[count++] = new MonitorLink( link_ids[i], dbrow[1] ); + } + else + { + Warning( "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); + } + mysql_free_result( result ); + } + n_linked_monitors = count; + } + } +} + +#if ZM_HAS_V4L +int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !device[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet, SignalCheckColour 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 ) ); + } + + 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 ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + const char *method = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + //============================================================================ + std::string plugins = dbrow[col]; col++; + int doNativeMotDet = atoi(dbrow[col]); col++; + //============================================================================ + + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = new LocalCamera( + id, + device, + channel, + format, + method, + cam_width, + cam_height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + extras + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose, + 0, + 0, + plugins, + doNativeMotDet + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // ZM_HAS_V4L + +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]; + if ( !protocol ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet 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, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + //============================================================================ + std::string plugins = dbrow[col]; col++; + int doNativeMotDet = atoi(dbrow[col]); col++; + //============================================================================ + + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = 0; + if ( protocol == "http" ) + { + camera = new RemoteCameraHttp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#if HAVE_LIBAVFORMAT + else if ( protocol == "rtsp" ) + { + camera = new RemoteCameraRtsp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#endif // HAVE_LIBAVFORMAT + else + { + Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); + } + + monitors[i] = new Monitor( + id, + name.c_str(), + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose, + 0, + 0, + plugins, + doNativeMotDet + + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, 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 ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); + } + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + //============================================================================ + std::string plugins = dbrow[col]; col++; + int doNativeMotDet = atoi(dbrow[col]); col++; + + //============================================================================ + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FileCamera( + id, + path, // File + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose, + 0, + 0, + plugins, + doNativeMotDet + + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +#if HAVE_LIBAVFORMAT +int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file ); + } + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + //============================================================================ + std::string plugins = dbrow[col]; col++; + int doNativeMotDet = atoi(dbrow[col]); col++; + + //============================================================================ + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FfmpegCamera( + id, + path, // File + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose, + 0, + 0, + plugins, + doNativeMotDet + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // HAVE_LIBAVFORMAT + +Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, UsedPl, DoNativeMotDet, SignalCheckColour 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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + Monitor *monitor = 0; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + std::string type = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + std::string linked_monitors = dbrow[col]; col++; + + std::string device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + //============================================================================ + std::string plugins = dbrow[col]; col++; + int doNativeMotDet = atoi(dbrow[col]); col++; + + //============================================================================ + + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = 0; + if ( type == "Local" ) + { +#if ZM_HAS_V4L + camera = new LocalCamera( + id, + device.c_str(), + channel, + format, + 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, + 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(), + 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 + { + 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, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose, + 0, + 0, + plugins, + doNativeMotDet + + ); + + int n_zones = 0; + if ( load_zones ) + { + Zone **zones = 0; + n_zones = Zone::Load( monitor, zones ); + monitor->AddZones( n_zones, 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 ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( monitor ); +} + +int Monitor::Capture() +{ + static int FirstCapture = 1; + int captureResult; + + int index = image_count%image_buffer_count; + Image* capture_image = image_buffer[index].image; + + if ( (deinterlacing & 0xff) == 4) { + if ( FirstCapture != 1 ) { + /* Copy the next image into the shared memory */ + capture_image->CopyBuffer(*(next_buffer.image)); + } + + /* Capture a new next image */ + captureResult = camera->Capture(*(next_buffer.image)); + + if ( FirstCapture ) { + FirstCapture = 0; + return 0; + } + + } else { + /* Capture directly into image buffer, avoiding the need to memcpy() */ + captureResult = camera->Capture(*capture_image); + } + + if ( captureResult != 0 ) + { + // Unable to capture image for temporary reason + // Fake a signal loss image + capture_image->Fill( signal_check_colour ); + captureResult = 0; + } else { + captureResult = 1; + } + + if ( captureResult == 1 ) + { + + /* Deinterlacing */ + if ( (deinterlacing & 0xff) == 1 ) { + capture_image->Deinterlace_Discard(); + } else if ( (deinterlacing & 0xff) == 2 ) { + capture_image->Deinterlace_Linear(); + } else if ( (deinterlacing & 0xff) == 3 ) { + capture_image->Deinterlace_Blend(); + } else if ( (deinterlacing & 0xff) == 4 ) { + capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff ); + } else if ( (deinterlacing & 0xff) == 5 ) { + capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); + } + + + if ( orientation != ROTATE_0 ) + { + switch ( orientation ) + { + case ROTATE_0 : + { + // No action required + break; + } + case ROTATE_90 : + case ROTATE_180 : + case ROTATE_270 : + { + capture_image->Rotate( (orientation-1)*90 ); + break; + } + case FLIP_HORI : + case FLIP_VERT : + { + capture_image->Flip( orientation==FLIP_HORI ); + break; + } + } + } + + } + if ( true ) { + + if ( (unsigned int)capture_image->Size() != camera->ImageSize() ) + { + Error( "Captured image does not match expected size, check width, height and colour depth" ); + return( -1 ); + } + + if ( ((unsigned int)index == shared_data->last_read_index) && (function > MONITOR) ) + { + Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); + time_t now = time(0); + double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); + time_t last_read_delta = now - shared_data->last_read_time; + if ( last_read_delta > (image_buffer_count/approxFps) ) + { + Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta ) + shared_data->last_read_index = image_buffer_count; + } + } + + gettimeofday( image_buffer[index].timestamp, NULL ); + if ( config.timestamp_on_capture ) + { + TimestampImage( capture_image, image_buffer[index].timestamp ); + } + shared_data->signal = CheckSignal(capture_image); + shared_data->last_write_index = index; + shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; + + image_count++; + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + time_t now = image_buffer[index].timestamp->tv_sec; + fps = double(fps_report_interval)/(now-last_fps_time); + //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); + //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); + Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); + last_fps_time = now; + } + + if ( shared_data->action & GET_SETTINGS ) + { + shared_data->brightness = camera->Brightness(); + shared_data->hue = camera->Hue(); + shared_data->colour = camera->Colour(); + shared_data->contrast = camera->Contrast(); + shared_data->action &= ~GET_SETTINGS; + } + if ( shared_data->action & SET_SETTINGS ) + { + camera->Brightness( shared_data->brightness ); + camera->Hue( shared_data->hue ); + camera->Colour( shared_data->colour ); + camera->Contrast( shared_data->contrast ); + shared_data->action &= ~SET_SETTINGS; + } + return( 0 ); + } + shared_data->signal = false; + return( -1 ); +} + +void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const +{ + if ( label_format[0] ) + { + // Expand the strftime macros first + char label_time_text[256]; + strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); + + char label_text[1024]; + const char *s_ptr = label_time_text; + char *d_ptr = label_text; + while ( *s_ptr && ((d_ptr-label_text) < (unsigned int)sizeof(label_text)) ) + { + if ( *s_ptr == '%' ) + { + bool found_macro = false; + switch ( *(s_ptr+1) ) + { + case 'N' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", name ); + found_macro = true; + break; + case 'Q' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", trigger_data->trigger_showtext ); + found_macro = true; + break; + case 'f' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time->tv_usec/10000 ); + found_macro = true; + break; + } + if ( found_macro ) + { + s_ptr += 2; + continue; + } + } + *d_ptr++ = *s_ptr++; + } + *d_ptr = '\0'; + ts_image->Annotate( label_text, label_coord ); + } +} + +bool Monitor::closeEvent() +{ + if ( event ) + { + if ( function == RECORD || function == MOCORD ) + { + gettimeofday( &(event->EndTime()), NULL ); + } + delete event; + event = 0; + return( true ); + } + return( false ); +} + +//----------------------------------------- + +/* + * NOTE Nextime's comment: + * + * OurCheckAlarms seems to be called only by DetectBlack method, and DetectBlack + * method is only called in a commented line instead of DetectMotion in zm_monitor.cpp. + * + * Probably this is just a dead code used for debugghing purpose, so, instead of fixing it + * it seems to be safe to just comment it out. + * + * Anyway, the issues with this code is that it assumes the image to be an RGB24 image, + * so, as i've discussed on IRC with mastertheknife, changes needed are: + * + * Check if the image is 24 or 32 bits ( pImage->Colours() says 3 for 24 and 4 for 32 bits, + * comparing it with ZM_COLOUR_RGB24 or ZM_COLOUR_RGB32 is the way ), and then + * manage che check using RGB_VAL_RED() and so on macros instead of just RED(). + * + * Be carefull that in 32 bit images we need to check also where the alpha channel is, so, + * (RGBA and BGRA) or (ABGR and ARGB) aren't the same! + * + * To check black pixels in 32 bit images i can do a more efficient way using + * RGBA_ZERO_ALPHA(pixel) == RGBA_ZERO_ALPHA(RGB_BLACK), but before of that i need to + * check where the alpha channel is and maybe convert it. + * Maybe this won't work as they assign "23" to black_thr, so, they are not checking + * if the pixel is black, but just "quasi" black is enough. + * + * Anyway, for the moment, comment out whole part. + */ + +/* +bool Monitor::OurCheckAlarms( Zone *zone, const Image *pImage ) +{ + Info("Entering OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + unsigned char black_thr = 23; + int min_alarm_score = 10; + int max_alarm_score = 99; + //bool alarm = false; + unsigned int score; + Polygon zone_polygon = zone->GetPolygon(); + Info("Got polygon of a zone. It has %d vertices.", zone_polygon.getNumCoords()); + + zone->ResetStats(); + Info("ResetStats done."); + + if ( !zone->CheckOverloadCount() ) + { + Info("CheckOverloadCount() return false, we'll return false."); + return( false ); + } + + Image *pMaskImage = new Image(pImage->Width(), pImage->Height(), ZM_COLOUR_GRAY8, pImage->SubpixelOrder()); + Info("Mask image created."); + + pMaskImage->Fill(BLACK); + Info("Mask image filled with BLACK."); + if (pImage->Colours() == ZM_COLOUR_GRAY8) + { + Info("Analysed image is not colored! Set score = 0."); + score = 0; + } + else + { + Info("Start processing image."); + //Process image + unsigned char *buffer = (unsigned char*)pImage->Buffer(); + unsigned char *mask_buffer = (unsigned char*)pMaskImage->Buffer(); + + int black_pixels_count = 0; + Info("Loop for black pixels counting and mask filling."); + while (buffer < (pImage->Buffer() + pImage->Size())) + { + if ( (RED(buffer) < black_thr) && (GREEN(buffer) < black_thr) && (BLUE(buffer) < black_thr) ) + { + *mask_buffer = WHITE; + black_pixels_count++; + } + buffer += pImage->Colours(); + mask_buffer++; + } + + if ( !black_pixels_count ) + { + delete pMaskImage; + return( false ); + } + score = (100*black_pixels_count)/zone_polygon.Area(); + Info("Number of black pixels is %d, zone polygon area is %d, score is %d", black_pixels_count, zone_polygon.Area(), score); + + if ( min_alarm_score && ( score < min_alarm_score) ) + { + delete pMaskImage; + return( false ); + } + if ( max_alarm_score && (score > max_alarm_score) ) + { + zone->SetOverloadCount(zone->GetOverloadFrames()); + delete pMaskImage; + return( false ); + } + } + + zone->SetScore(score); + Info("Score have been set in zone."); + //Get mask + Rgb alarm_colour = RGB_RED; + Image *tempImage = pMaskImage->HighlightEdges(alarm_colour, &zone_polygon.Extent() ); + Info("After HighlightEdges"); + + zone->SetAlarmImage(tempImage); + Info("After SetAlarmImage"); + delete pMaskImage; + Info("After Delete pMaskImage"); + delete tempImage; + + Info("Leaving OurCheckAlarms >>>>>>>>>>>>>>>>>>>>>>>>>>>>"); + return true; +} + +unsigned int Monitor::DetectBlack(const Image &comp_image, Event::StringSet &zoneSet ) +{ + Info("Entering DetectBlack >>>>>>>>>>>>>>>>>>>>>>>>>>"); + bool alarm = false; + unsigned int score = 0; + + if ( n_zones <= 0 ) return( alarm ); + +// Coord alarm_centre; +// int top_score = -1; + + // Find all alarm pixels in active zones + Info("Number of zones to process %d", n_zones); + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() ) + { + continue; + } + Debug( 3, "Checking active zone %s", zone->Label() ); + Info( "Checking active zone %s", zone->Label() ); + if ( OurCheckAlarms( zone, &comp_image ) ) + { + Info("OurCheckAlarm is TRUE!!!!!!"); + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + Info( "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); +// if ( config.opt_control && track_motion ) +// { +// if ( (int)zone->Score() > top_score ) +// { +// top_score = zone->Score(); +// alarm_centre = zone->GetAlarmCentre(); +// } +// } + } + Info( "Finish checking active zone %s", zone->Label() ); + } + + +// if ( top_score > 0 ) +// { +// shared_data->alarm_x = alarm_centre.X(); +// shared_data->alarm_y = alarm_centre.Y(); +// +// Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); +// } +// else +// { +// shared_data->alarm_x = shared_data->alarm_y = -1; +// } + + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + Info("Leaving DetectBlack <<<<<<<<<<<<<<<<<<<<<<<<<<<"); + return( score?score:alarm ); +} + +*/ +//----------------------------------------------------------------------------------------------- + + + +unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) +{ + bool alarm = false; + unsigned int score = 0; + + if ( n_zones <= 0 ) return( alarm ); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); + } + ref_image.WriteJpeg( diag_path ); + } + + ref_image.Delta( comp_image, &delta_image); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); + } + delta_image.WriteJpeg( diag_path ); + } + + // Blank out all exclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + zone->ClearAlarm(); + if ( !zone->IsInactive() ) + { + continue; + } + Debug( 3, "Blanking inactive zone %s", zone->Label() ); + delta_image.Fill( RGB_BLACK, zone->GetPolygon() ); + } + + // Check preclusive zones first + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsPreclusive() ) + { + continue; + } + Debug( 3, "Checking preclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + //zone->ResetStats(); + } + } + + Coord alarm_centre; + int top_score = -1; + + if ( alarm ) + { + alarm = false; + score = 0; + } + else + { + // Find all alarm pixels in active zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() ) + { + continue; + } + Debug( 3, "Checking active zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( (int)zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } + + if ( alarm ) + { + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsInclusive() ) + { + continue; + } + Debug( 3, "Checking inclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( zone->Score() > (unsigned int)top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } + } + else + { + // Find all alarm pixels in exclusive zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsExclusive() ) + { + continue; + } + Debug( 3, "Checking exclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + } + } + } + } + + if ( top_score > 0 ) + { + shared_data->alarm_x = alarm_centre.X(); + shared_data->alarm_y = alarm_centre.Y(); + + Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); + } + else + { + shared_data->alarm_x = shared_data->alarm_y = -1; + } + + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + return( score?score:alarm ); +} + +bool Monitor::DumpSettings( char *output, bool verbose ) +{ + output[0] = 0; + + sprintf( output+strlen(output), "Id : %d\n", id ); + sprintf( output+strlen(output), "Name : %s\n", name ); + sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); +#if ZM_HAS_V4L + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); + sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); + sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); + } + else +#endif // ZM_HAS_V4L + if ( camera->IsRemote() ) + { + sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); + sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); + sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); + sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); + } + else if ( camera->IsFile() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); + } +#if HAVE_LIBAVFORMAT + else if ( camera->IsFfmpeg() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); + } +#endif // HAVE_LIBAVFORMAT + sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); + sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); +#if ZM_HAS_V4L + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); + } +#endif // ZM_HAS_V4L + sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); + sprintf( output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); + sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); + sprintf( output+strlen(output), "Label Format : %s\n", label_format ); + sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); + sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); + sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); + sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); + sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); + sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); + sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); + sprintf( output+strlen(output), "Section Length : %d\n", section_length ); + sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); + sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); + sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); + sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); + sprintf( output+strlen(output), "Function: %d - %s\n", function, + function==NONE?"None":( + function==MONITOR?"Monitor Only":( + function==MODECT?"Motion Detection":( + function==RECORD?"Continuous Record":( + function==MOCORD?"Continuous Record with Motion Detection":( + function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" + )))))); + sprintf( output+strlen(output), "Zones : %d\n", n_zones ); + for ( int i = 0; i < n_zones; i++ ) + { + zones[i]->DumpSettings( output+strlen(output), verbose ); + } + return( true ); +} + +bool MonitorStream::checkSwapPath( const char *path, bool create_path ) +{ + uid_t uid = getuid(); + gid_t gid = getgid(); + + struct stat stat_buf; + if ( stat( path, &stat_buf ) < 0 ) + { + if ( create_path && errno == ENOENT ) + { + Debug( 3, "Swap path '%s' missing, creating", path ); + if ( mkdir( path, 0755 ) ) + { + Error( "Can't mkdir %s: %s", path, strerror(errno)); + return( false ); + } + if ( stat( path, &stat_buf ) < 0 ) + { + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); + } + } + else + { + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); + } + } + if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", path ); + return( false ); + } + + mode_t mask = 0; + if ( uid == stat_buf.st_uid ) + { + // If we are the owner + mask = 00700; + } + else if ( gid == stat_buf.st_gid ) + { + // If we are in the owner group + mask = 00070; + } + else + { + // We are neither the owner nor in the group + mask = 00007; + } + + if ( (stat_buf.st_mode & mask) != mask ) + { + Error( "Insufficient permissions on swap image path '%s'", path ); + return( false ); + } + return( true ); +} + +void MonitorStream::processCommand( const CmdMsg *msg ) +{ + Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ); + // Check for incoming command + switch( (MsgCommand)msg->msg_data[0] ) + { + case CMD_PAUSE : + { + Debug( 1, "Got PAUSE command" ); + + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + last_frame_sent = TV_2_FLOAT( now ); + break; + } + case CMD_PLAY : + { + Debug( 1, "Got PLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ZM_RATE_BASE; + break; + } + case CMD_VARPLAY : + { + Debug( 1, "Got VARPLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; + break; + } + case CMD_STOP : + { + Debug( 1, "Got STOP command" ); + + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + break; + } + case CMD_FASTFWD : + { + Debug( 1, "Got FAST FWD command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case 2 * ZM_RATE_BASE : + replay_rate = 5 * ZM_RATE_BASE; + break; + case 5 * ZM_RATE_BASE : + replay_rate = 10 * ZM_RATE_BASE; + break; + case 10 * ZM_RATE_BASE : + replay_rate = 25 * ZM_RATE_BASE; + break; + case 25 * ZM_RATE_BASE : + case 50 * ZM_RATE_BASE : + replay_rate = 50 * ZM_RATE_BASE; + break; + default : + replay_rate = 2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_SLOWFWD : + { + Debug( 1, "Got SLOW FWD command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = 1; + break; + } + case CMD_SLOWREV : + { + Debug( 1, "Got SLOW REV command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = -1; + break; + } + case CMD_FASTREV : + { + Debug( 1, "Got FAST REV command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case -2 * ZM_RATE_BASE : + replay_rate = -5 * ZM_RATE_BASE; + break; + case -5 * ZM_RATE_BASE : + replay_rate = -10 * ZM_RATE_BASE; + break; + case -10 * ZM_RATE_BASE : + replay_rate = -25 * ZM_RATE_BASE; + break; + case -25 * ZM_RATE_BASE : + case -50 * ZM_RATE_BASE : + replay_rate = -50 * ZM_RATE_BASE; + break; + default : + replay_rate = -2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_ZOOMIN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); + switch ( zoom ) + { + case 100: + zoom = 150; + break; + case 150: + zoom = 200; + break; + case 200: + zoom = 300; + break; + case 300: + zoom = 400; + break; + case 400: + default : + zoom = 500; + break; + } + break; + } + case CMD_ZOOMOUT : + { + Debug( 1, "Got ZOOM OUT command" ); + switch ( zoom ) + { + case 500: + zoom = 400; + break; + case 400: + zoom = 300; + break; + case 300: + zoom = 200; + break; + case 200: + zoom = 150; + break; + case 150: + default : + zoom = 100; + break; + } + break; + } + case CMD_PAN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got PAN command, to %d,%d", x, y ); + break; + } + case CMD_SCALE : + { + scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + Debug( 1, "Got SCALE command, to %d", scale ); + break; + } + case CMD_QUERY : + { + Debug( 1, "Got QUERY command, sending STATUS" ); + break; + } + default : + { + Error( "Got unexpected command %d", msg->msg_data[0] ); + break; + } + } + + struct { + int id; + int state; + double fps; + int buffer_level; + int rate; + double delay; + int zoom; + bool delayed; + bool paused; + bool enabled; + bool forced; + } status_data; + + status_data.id = monitor->Id(); + status_data.fps = monitor->GetFPS(); + status_data.state = monitor->shared_data->state; + if ( playback_buffer > 0 ) + status_data.buffer_level = (MOD_ADD( (temp_write_index-temp_read_index), 0, temp_image_buffer_count )*100)/temp_image_buffer_count; + else + status_data.buffer_level = 0; + status_data.delayed = delayed; + status_data.paused = paused; + status_data.rate = replay_rate; + status_data.delay = TV_2_FLOAT( now ) - TV_2_FLOAT( last_frame_timestamp ); + status_data.zoom = zoom; + //status_data.enabled = monitor->shared_data->active; + status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; + status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; + Debug( 2, "L:%d, D:%d, P:%d, R:%d, d:%.3f, Z:%d, E:%d F:%d", + status_data.buffer_level, + status_data.delayed, + status_data.paused, + status_data.rate, + status_data.delay, + status_data.zoom, + status_data.enabled, + status_data.forced + ); + + DataMsg status_msg; + status_msg.msg_type = MSG_DATA_WATCH; + memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) ); + int nbytes = 0; + if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 ) + { + //if ( errno != EAGAIN ) + { + Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + //exit( -1 ); + } + } + + updateFrameRate( monitor->GetFPS() ); +} + +bool MonitorStream::sendFrame( const char *filepath, struct timeval *timestamp ) +{ + bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); + + if ( type != STREAM_JPEG ) + send_raw = false; + if ( !config.timestamp_on_capture && timestamp ) + send_raw = false; + + if ( !send_raw ) + { + Image temp_image( filepath ); + + return( sendFrame( &temp_image, timestamp ) ); + } + else + { + int img_buffer_size = 0; + static unsigned char img_buffer[ZM_MAX_IMAGE_SIZE]; + + FILE *fdj = NULL; + if ( (fdj = fopen( filepath, "r" )) ) + { + img_buffer_size = fread( img_buffer, 1, sizeof(img_buffer), fdj ); + fclose( fdj ); + } + else + { + Error( "Can't open %s: %s", filepath, strerror(errno) ); + return( false ); + } + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 2; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + + last_frame_sent = TV_2_FLOAT( now ); + + return( true ); + } + return( false ); +} + +bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) +{ + Image *send_image = prepareImage( image ); + if ( !config.timestamp_on_capture && timestamp ) + monitor->TimestampImage( send_image, timestamp ); + +#if HAVE_LIBAVCODEC + if ( type == STREAM_MPEG ) + { + if ( !vid_stream ) + { + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); + } + static struct timeval base_time; + struct DeltaTimeval delta_time; + if ( !frame_count ) + base_time = *timestamp; + DELTA_TIMEVAL( delta_time, *timestamp, base_time, DT_PREC_3 ); + /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta ); + } + else +#endif // HAVE_LIBAVCODEC + { + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + + int img_buffer_size = 0; + unsigned char *img_buffer = temp_img_buffer; + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + switch( type ) + { + case STREAM_JPEG : + send_image->EncodeJpeg( img_buffer, &img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n" ); + break; + case STREAM_RAW : + fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); + img_buffer = (uint8_t*)send_image->Buffer(); + img_buffer_size = send_image->Size(); + break; + case STREAM_ZIP : + fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); + unsigned long zip_buffer_size; + send_image->Zip( img_buffer, &zip_buffer_size ); + img_buffer_size = zip_buffer_size; + break; + default : + Fatal( "Unexpected frame type %d", type ); + break; + } + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 1.5; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); +} + +void MonitorStream::runStream() +{ + if ( type == STREAM_SINGLE ) + { + // Not yet migrated over to stream class + monitor->SingleImage( scale ); + return; + } + + openComms(); + + checkInitialised(); + + updateFrameRate( monitor->GetFPS() ); + + if ( type == STREAM_JPEG ) + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + + int last_read_index = monitor->image_buffer_count; + + time_t stream_start_time; + time( &stream_start_time ); + + frame_count = 0; + + temp_image_buffer = 0; + temp_image_buffer_count = playback_buffer; + temp_read_index = temp_image_buffer_count; + temp_write_index = temp_image_buffer_count; + + char swap_path[PATH_MAX] = ""; + bool buffered_playback = false; + + if ( connkey && playback_buffer > 0 ) + { + Debug( 2, "Checking swap image location" ); + Debug( 3, "Checking swap image path" ); + strncpy( swap_path, config.path_swap, sizeof(swap_path) ); + if ( checkSwapPath( swap_path, false ) ) + { + snprintf( &(swap_path[strlen(swap_path)]), sizeof(swap_path)-strlen(swap_path), "/zmswap-m%d", monitor->Id() ); + if ( checkSwapPath( swap_path, true ) ) + { + snprintf( &(swap_path[strlen(swap_path)]), sizeof(swap_path)-strlen(swap_path), "/zmswap-q%06d", connkey ); + if ( checkSwapPath( swap_path, true ) ) + { + buffered_playback = true; + } + } + } + + if ( !buffered_playback ) + { + Error( "Unable to validate swap image path, disabling buffered playback" ); + } + else + { + Debug( 2, "Assigning temporary buffer" ); + temp_image_buffer = new SwapImage[temp_image_buffer_count]; + memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); + Debug( 2, "Assigned temporary buffer" ); + } + } + + float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) + while ( !zm_terminate ) + { + bool got_command = false; + if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) + { + break; + } + + gettimeofday( &now, NULL ); + + if ( connkey ) + { + while(checkCommandQueue()) { + got_command = true; + } + } + + //bool frame_sent = false; + if ( buffered_playback && delayed ) + { + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Debug( 1, "Exceeded temporary streaming buffer" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + else + { + if ( !paused ) + { + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); + //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index ); + SwapImage *swap_image = &temp_image_buffer[temp_index]; + + if ( !swap_image->valid ) + { + paused = true; + delayed = true; + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count ); + } + else + { + //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); + double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate; + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + + //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) ); + // If the next frame is due + if ( actual_delta_time > expected_delta_time ) + { + //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time ); + if ( temp_index%frame_mod == 0 ) + { + Debug( 2, "Sending delayed frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + //frame_sent = true; + } + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count ); + } + } + } + else if ( step != 0 ) + { + temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count ); + + SwapImage *swap_image = &temp_image_buffer[temp_read_index]; + + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + //frame_sent = true; + step = 0; + } + else + { + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); + + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( got_command || actual_delta_time > 5 ) + { + // Send keepalive + Debug( 2, "Sending keepalive frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + //frame_sent = true; + } + } + } + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Warning( "Rewound over write index, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + } + if ( (unsigned int)last_read_index != monitor->shared_data->last_write_index ) + { + int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; + last_read_index = monitor->shared_data->last_write_index; + //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); + if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) + { + if ( !paused && !delayed ) + { + // Send the next frame + Monitor::Snapshot *snap = &monitor->image_buffer[index]; + + if ( !sendFrame( snap->image, snap->timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); + //frame_sent = true; + + temp_read_index = temp_write_index; + } + } + if ( buffered_playback ) + { + if ( monitor->shared_data->valid ) + { + if ( monitor->image_buffer[index].timestamp->tv_sec ) + { + int temp_index = temp_write_index%temp_image_buffer_count; + Debug( 2, "Storing frame %d", temp_index ); + if ( !temp_image_buffer[temp_index].valid ) + { + snprintf( temp_image_buffer[temp_index].file_name, sizeof(temp_image_buffer[0].file_name), "%s/zmswap-i%05d.jpg", swap_path, temp_index ); + temp_image_buffer[temp_index].valid = true; + } + memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) ); + monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); + temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count ); + if ( temp_write_index == temp_read_index ) + { + // Go back to live viewing + Warning( "Exceeded temporary buffer, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + } + else + { + Warning( "Unable to store frame as timestamp invalid" ); + } + } + else + { + Warning( "Unable to store frame as shared memory invalid" ); + } + } + frame_count++; + } + usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); + if ( ttl ) + { + if ( (now.tv_sec - stream_start_time) > ttl ) + { + break; + } + } + if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) + { + Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); + break; + } + } + if ( buffered_playback ) + { + char swap_path[PATH_MAX] = ""; + + snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", config.path_swap, monitor->Id(), connkey ); + Debug( 1, "Cleaning swap files from %s", swap_path ); + struct stat stat_buf; + if ( stat( swap_path, &stat_buf ) < 0 ) + { + if ( errno != ENOENT ) + { + Error( "Can't stat '%s': %s", swap_path, strerror(errno) ); + } + } + else if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", swap_path ); + } + else + { + char glob_pattern[PATH_MAX] = ""; + + snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path ); + glob_t pglob; + int glob_status = glob( glob_pattern, 0, 0, &pglob ); + if ( glob_status != 0 ) + { + if ( glob_status < 0 ) + { + Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) ); + } + else + { + Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status ); + } + } + else + { + for ( unsigned int i = 0; i < pglob.gl_pathc; i++ ) + { + if ( unlink( pglob.gl_pathv[i] ) < 0 ) + { + Error( "Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno) ); + } + } + } + globfree( &pglob ); + if ( rmdir( swap_path ) < 0 ) + { + Error( "Can't rmdir '%s': %s", swap_path, strerror(errno) ); + } + } + } + closeComms(); +} + +void Monitor::SingleImage( int scale) +{ + int img_buffer_size = 0; + static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); +} + +void Monitor::SingleImageRaw( int scale) +{ + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + + fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); + fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); + fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); +} + +void Monitor::SingleImageZip( int scale) +{ + unsigned long img_buffer_size = 0; + static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->Zip( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); +} diff --git a/src/zm_monitor.cpp.orig b/src/zm_monitor.cpp.orig new file mode 100644 index 000000000..298ad2b3a --- /dev/null +++ b/src/zm_monitor.cpp.orig @@ -0,0 +1,3889 @@ +// +// ZoneMinder Monitor Class Implementation, $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. +// + +#include +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_time.h" +#include "zm_mpeg.h" +#include "zm_signal.h" +#include "zm_monitor.h" +#if ZM_HAS_V4L +#include "zm_local_camera.h" +#endif // ZM_HAS_V4L +#include "zm_remote_camera.h" +#include "zm_remote_camera_http.h" +#if HAVE_LIBAVFORMAT +#include "zm_remote_camera_rtsp.h" +#endif // HAVE_LIBAVFORMAT +#include "zm_file_camera.h" +#if HAVE_LIBAVFORMAT +#include "zm_ffmpeg_camera.h" +#endif // HAVE_LIBAVFORMAT + +#if ZM_MEM_MAPPED +#include +#include +#else // ZM_MEM_MAPPED +#include +#include +#endif // ZM_MEM_MAPPED + +Monitor::MonitorLink::MonitorLink( int p_id, const char *p_name ) : id( p_id ) +{ + strncpy( name, p_name, sizeof(name) ); + +#if ZM_MEM_MAPPED + map_fd = -1; + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); +#else // ZM_MEM_MAPPED + shm_id = 0; +#endif // ZM_MEM_MAPPED + mem_size = 0; + mem_ptr = 0; + + last_event = 0; + last_state = IDLE; + + last_connect_time = 0; + connected = false; +} + +Monitor::MonitorLink::~MonitorLink() +{ + disconnect(); +} + +bool Monitor::MonitorLink::connect() +{ + if ( !last_connect_time || (time( 0 ) - last_connect_time) > 60 ) + { + last_connect_time = time( 0 ); + + mem_size = sizeof(SharedData) + sizeof(TriggerData); + + Debug( 1, "link.mem.size=%d", mem_size ); +#if ZM_MEM_MAPPED + map_fd = open( mem_file, O_RDWR, (mode_t)0600 ); + if ( map_fd < 0 ) + { + Debug( 3, "Can't open linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + + struct stat map_stat; + if ( fstat( map_fd, &map_stat ) < 0 ) + { + Error( "Can't stat linked memory map file %s: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + + if ( map_stat.st_size == 0 ) + { + Error( "Linked memory map file %s is empty: %s", mem_file, strerror(errno) ); + disconnect(); + return( false ); + } + else if ( map_stat.st_size < mem_size ) + { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + disconnect(); + return( false ); + } + + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) + { + Error( "Can't map file %s (%d bytes) to memory: %s", mem_file, mem_size, strerror(errno) ); + disconnect(); + return( false ); + } +#else // ZM_MEM_MAPPED + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, 0700 ); + if ( shm_id < 0 ) + { + Debug( 3, "Can't shmget link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Debug( 3, "Can't shmat link memory: %s", strerror(errno) ); + connected = false; + return( false ); + } +#endif // ZM_MEM_MAPPED + + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + + if ( !shared_data->valid ) + { + Debug( 3, "Linked memory not initialised by capture daemon" ); + disconnect(); + return( false ); + } + + last_state = shared_data->state; + last_event = shared_data->last_event; + connected = true; + + return( true ); + } + return( false ); +} + +bool Monitor::MonitorLink::disconnect() +{ + if ( connected ) + { + connected = false; + +#if ZM_MEM_MAPPED + if ( mem_ptr > 0 ) + { + msync( mem_ptr, mem_size, MS_ASYNC ); + munmap( mem_ptr, mem_size ); + } + if ( map_fd >= 0 ) + close( map_fd ); + + map_fd = -1; +#else // ZM_MEM_MAPPED + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } + + shm_id = 0; + + if ( shm_data.shm_nattch <= 1 ) + { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) + { + Debug( 3, "Can't shmctl: %s", strerror(errno) ); + return( false ); + } + } + + if ( shmdt( mem_ptr ) < 0 ) + { + Debug( 3, "Can't shmdt: %s", strerror(errno) ); + return( false ); + } + +#endif // ZM_MEM_MAPPED + mem_size = 0; + mem_ptr = 0; + } + return( true ); +} + +bool Monitor::MonitorLink::isAlarmed() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM ); +} + +bool Monitor::MonitorLink::inAlarm() +{ + if ( !connected ) + { + return( false ); + } + return( shared_data->state == ALARM || shared_data->state == ALERT ); +} + +bool Monitor::MonitorLink::hasAlarmed() +{ + if ( shared_data->state == ALARM ) + { + return( true ); + } + else if( shared_data->last_event != last_event ) + { + last_event = shared_data->last_event; + return( true ); + } + return( false ); +} + +Monitor::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, + const char *p_event_prefix, + const char *p_label_format, + const Coord &p_label_coord, + 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_capture_delay, + int p_alarm_capture_delay, + int p_fps_report_interval, + int p_ref_blend_perc, + bool p_track_motion, + Rgb p_signal_check_colour, + Purpose p_purpose, + int p_n_zones, + Zone *p_zones[] +) : id( p_id ), + function( (Function)p_function ), + enabled( p_enabled ), + width( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Height():p_camera->Width() ), + height( (p_orientation==ROTATE_90||p_orientation==ROTATE_270)?p_camera->Width():p_camera->Height() ), + orientation( (Orientation)p_orientation ), + deinterlacing( p_deinterlacing ), + label_coord( p_label_coord ), + image_buffer_count( p_image_buffer_count ), + warmup_count( p_warmup_count ), + pre_event_count( p_pre_event_count ), + post_event_count( p_post_event_count ), + stream_replay_buffer( p_stream_replay_buffer ), + section_length( p_section_length ), + frame_skip( p_frame_skip ), + capture_delay( p_capture_delay ), + alarm_capture_delay( p_alarm_capture_delay ), + alarm_frame_count( p_alarm_frame_count ), + fps_report_interval( p_fps_report_interval ), + ref_blend_perc( p_ref_blend_perc ), + track_motion( p_track_motion ), + signal_check_colour( p_signal_check_colour ), + delta_image( width, height, ZM_COLOUR_GRAY8, ZM_SUBPIX_ORDER_NONE ), + ref_image( width, height, p_camera->Colours(), p_camera->SubpixelOrder() ), + purpose( p_purpose ), + camera( p_camera ), + n_zones( p_n_zones ), + zones( p_zones ) +{ + strncpy( name, p_name, sizeof(name) ); + + strncpy( event_prefix, p_event_prefix, sizeof(event_prefix) ); + strncpy( label_format, p_label_format, sizeof(label_format) ); + + // Change \n to actual line feeds + char *token_ptr = label_format; + const char *token_string = "\n"; + while( ( token_ptr = strstr( token_ptr, token_string ) ) ) + { + if ( *(token_ptr+1) ) + { + *token_ptr = '\n'; + token_ptr++; + strcpy( token_ptr, token_ptr+1 ); + } + else + { + *token_ptr = '\0'; + break; + } + } + + fps = 0.0; + event_count = 0; + image_count = 0; + ready_count = warmup_count; + first_alarm_count = 0; + last_alarm_count = 0; + state = IDLE; + + if ( alarm_frame_count < 1 ) + alarm_frame_count = 1; + else if ( alarm_frame_count > MAX_PRE_ALARM_FRAMES ) + alarm_frame_count = MAX_PRE_ALARM_FRAMES; + + auto_resume_time = 0; + + if ( strcmp( config.event_close_mode, "time" ) == 0 ) + event_close_mode = CLOSE_TIME; + else if ( strcmp( config.event_close_mode, "alarm" ) == 0 ) + event_close_mode = CLOSE_ALARM; + else + event_close_mode = CLOSE_IDLE; + + Debug( 1, "monitor purpose=%d", purpose ); + + mem_size = sizeof(SharedData) + + sizeof(TriggerData) + + (image_buffer_count*sizeof(struct timeval)) + + (image_buffer_count*camera->ImageSize()) + + 64; /* Padding used to permit aligning the images buffer to 16 byte boundary */ + + Debug( 1, "mem.size=%d", mem_size ); +#if ZM_MEM_MAPPED + snprintf( mem_file, sizeof(mem_file), "%s/zm.mmap.%d", config.path_map, id ); + map_fd = open( mem_file, O_RDWR|O_CREAT, (mode_t)0600 ); + if ( map_fd < 0 ) + Fatal( "Can't open memory map file %s, probably not enough space free: %s", mem_file, strerror(errno) ); + struct stat map_stat; + if ( fstat( map_fd, &map_stat ) < 0 ) + Fatal( "Can't stat memory map file %s: %s", mem_file, strerror(errno) ); + if ( map_stat.st_size != mem_size && purpose == CAPTURE ) + { + // Allocate the size + if ( ftruncate( map_fd, mem_size ) < 0 ) + Fatal( "Can't extend memory map file %s to %d bytes: %s", mem_file, mem_size, strerror(errno) ); + } + else if ( map_stat.st_size != mem_size ) + { + Error( "Got unexpected memory map file size %ld, expected %d", map_stat.st_size, mem_size ); + } + + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_LOCKED, map_fd, 0 ); + if ( mem_ptr == MAP_FAILED ) + if ( errno == EAGAIN ) + { + Debug( 1, "Unable to map file %s (%d bytes) to locked memory, trying unlocked", mem_file, mem_size ); + mem_ptr = (unsigned char *)mmap( NULL, mem_size, PROT_READ|PROT_WRITE, MAP_SHARED, map_fd, 0 ); + } + if ( mem_ptr == MAP_FAILED ) + Fatal( "Can't map file %s (%d bytes) to memory: %s(%d)", mem_file, mem_size, strerror(errno), errno ); +#else // ZM_MEM_MAPPED + shm_id = shmget( (config.shm_key&0xffff0000)|id, mem_size, IPC_CREAT|0700 ); + if ( shm_id < 0 ) + { + Error( "Can't shmget, probably not enough shared memory space free: %s", strerror(errno)); + exit( -1 ); + } + mem_ptr = (unsigned char *)shmat( shm_id, 0, 0 ); + if ( mem_ptr < 0 ) + { + Error( "Can't shmat: %s", strerror(errno)); + exit( -1 ); + } +#endif // ZM_MEM_MAPPED + + shared_data = (SharedData *)mem_ptr; + trigger_data = (TriggerData *)((char *)shared_data + sizeof(SharedData)); + struct timeval *shared_timestamps = (struct timeval *)((char *)trigger_data + sizeof(TriggerData)); + unsigned char *shared_images = (unsigned char *)((char *)shared_timestamps + (image_buffer_count*sizeof(struct timeval))); + + if(((unsigned long)shared_images % 16) != 0) { + /* Align images buffer to nearest 16 byte boundary */ + Debug(3,"Aligning shared memory images to the next 16 byte boundary"); + shared_images = (uint8_t*)((unsigned long)shared_images + (16 - ((unsigned long)shared_images % 16))); + } + + if ( purpose == CAPTURE ) + { + memset( mem_ptr, 0, mem_size ); + shared_data->size = sizeof(SharedData); + shared_data->active = enabled; + shared_data->signal = false; + shared_data->state = IDLE; + shared_data->last_write_index = image_buffer_count; + shared_data->last_read_index = image_buffer_count; + shared_data->last_write_time = 0; + shared_data->last_event = 0; + shared_data->action = (Action)0; + shared_data->brightness = -1; + shared_data->hue = -1; + shared_data->colour = -1; + shared_data->contrast = -1; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + shared_data->format = camera->SubpixelOrder(); + shared_data->imagesize = camera->ImageSize(); + trigger_data->size = sizeof(TriggerData); + trigger_data->trigger_state = TRIGGER_CANCEL; + trigger_data->trigger_score = 0; + trigger_data->trigger_cause[0] = 0; + trigger_data->trigger_text[0] = 0; + trigger_data->trigger_showtext[0] = 0; + shared_data->valid = true; + } + else if ( purpose == ANALYSIS ) + { + shared_data->state = IDLE; + shared_data->last_read_time = 0; + shared_data->alarm_x = -1; + shared_data->alarm_y = -1; + } + + if ( !shared_data->valid ) + { + if ( purpose != QUERY ) + { + Error( "Shared data not initialised by capture daemon" ); + exit( -1 ); + } + else + { + Warning( "Shared data not initialised by capture daemon, some query functions may not be available or produce invalid results" ); + } + } + + image_buffer = new Snapshot[image_buffer_count]; + for ( int i = 0; i < image_buffer_count; i++ ) + { + image_buffer[i].timestamp = &(shared_timestamps[i]); + image_buffer[i].image = new Image( width, height, camera->Colours(), camera->SubpixelOrder(), &(shared_images[i*camera->ImageSize()]) ); + image_buffer[i].image->HoldBuffer(true); /* Don't release the internal buffer or replace it with another */ + } + if ( (deinterlacing & 0xff) == 4) + { + /* Four field motion adaptive deinterlacing in use */ + /* Allocate a buffer for the next image */ + next_buffer.image = new Image( width, height, camera->Colours(), camera->SubpixelOrder()); + next_buffer.timestamp = new struct timeval; + } + if ( !n_zones ) + { + n_zones = 1; + zones = new Zone *[1]; + Coord coords[4] = { Coord( 0, 0 ), Coord( width-1, 0 ), Coord( width-1, height-1 ), Coord( 0, height-1 ) }; + zones[0] = new Zone( this, 0, "All", Zone::ACTIVE, Polygon( sizeof(coords)/sizeof(*coords), coords ), RGB_RED, Zone::BLOBS ); + } + start_time = last_fps_time = time( 0 ); + + event = 0; + + Debug( 1, "Monitor %s has function %d", name, function ); + Debug( 1, "Monitor %s LBF = '%s', LBX = %d, LBY = %d", name, label_format, label_coord.X(), label_coord.Y() ); + Debug( 1, "Monitor %s IBC = %d, WUC = %d, pEC = %d, PEC = %d, EAF = %d, FRI = %d, RBP = %d, FM = %d", name, image_buffer_count, warmup_count, pre_event_count, post_event_count, alarm_frame_count, fps_report_interval, ref_blend_perc, track_motion ); + + if ( purpose == ANALYSIS ) + { + static char path[PATH_MAX]; + + strncpy( path, config.dir_events, sizeof(path) ); + + struct stat statbuf; + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + } + + snprintf( path, sizeof(path), "%s/%d", config.dir_events, id ); + + errno = 0; + stat( path, &statbuf ); + if ( errno == ENOENT || errno == ENOTDIR ) + { + if ( mkdir( path, 0755 ) ) + { + Error( "Can't make %s: %s", path, strerror(errno)); + } + char temp_path[PATH_MAX]; + snprintf( temp_path, sizeof(temp_path), "%d", id ); + if ( chdir( config.dir_events ) < 0 ) + Fatal( "Can't change directory to '%s': %s", config.dir_events, strerror(errno) ); + if ( symlink( temp_path, name ) < 0 ) + Fatal( "Can't symlink '%s' to '%s': %s", temp_path, name, strerror(errno) ); + if ( chdir( ".." ) < 0 ) + Fatal( "Can't change to parent directory: %s", strerror(errno) ); + } + + while( shared_data->last_write_index == image_buffer_count && shared_data->last_write_time == 0) + { + Warning( "Waiting for capture daemon" ); + sleep( 1 ); + } + ref_image.Assign( width, height, camera->Colours(), camera->SubpixelOrder(), image_buffer[shared_data->last_write_index].image->Buffer(), camera->ImageSize()); + + n_linked_monitors = 0; + linked_monitors = 0; + ReloadLinkedMonitors( p_linked_monitors ); + } +} + +Monitor::~Monitor() +{ + if ( event ) + Info( "%s: %03d - Closing event %d, shutting down", name, image_count, event->Id() ); + closeEvent(); + + if ( (deinterlacing & 0xff) == 4) + { + delete next_buffer.image; + delete next_buffer.timestamp; + } + for ( int i = 0; i < image_buffer_count; i++ ) + { + delete image_buffer[i].image; + } + delete[] image_buffer; + + for ( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + + delete camera; + + if ( purpose == ANALYSIS ) + { + shared_data->state = state = IDLE; + shared_data->last_read_index = image_buffer_count; + shared_data->last_read_time = 0; + } + else if ( purpose == CAPTURE ) + { + shared_data->valid = false; + memset( mem_ptr, 0, mem_size ); + } + +#if ZM_MEM_MAPPED + if ( msync( mem_ptr, mem_size, MS_SYNC ) < 0 ) + Error( "Can't msync: %s", strerror(errno) ); + if ( munmap( mem_ptr, mem_size ) < 0 ) + Fatal( "Can't munmap: %s", strerror(errno) ); + close( map_fd ); +#else // ZM_MEM_MAPPED + struct shmid_ds shm_data; + if ( shmctl( shm_id, IPC_STAT, &shm_data ) < 0 ) + { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + if ( shm_data.shm_nattch <= 1 ) + { + if ( shmctl( shm_id, IPC_RMID, 0 ) < 0 ) + { + Error( "Can't shmctl: %s", strerror(errno) ); + exit( -1 ); + } + } +#endif // ZM_MEM_MAPPED +} + +void Monitor::AddZones( int p_n_zones, Zone *p_zones[] ) +{ + for ( int i = 0; i < n_zones; i++ ) + delete zones[i]; + delete[] zones; + n_zones = p_n_zones; + zones = p_zones; +} + +Monitor::State Monitor::GetState() const +{ + return( (State)shared_data->state ); +} + +int Monitor::GetImage( int index, int scale ) const +{ + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } + + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; + Image snap_image( *(snap->image) ); + + if ( scale != ZM_SCALE_BASE ) + { + snap_image.Scale( scale ); + } + + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + if ( !config.timestamp_on_capture ) + { + TimestampImage( &snap_image, snap->timestamp ); + } + snap_image.WriteJpeg( filename ); + } + else + { + Error( "Unable to generate image, no images in buffer" ); + } + return( 0 ); +} + +struct timeval Monitor::GetTimestamp( int index ) const +{ + if ( index < 0 || index > image_buffer_count ) + { + index = shared_data->last_write_index; + } + + if ( index != image_buffer_count ) + { + Snapshot *snap = &image_buffer[index]; + + return( *(snap->timestamp) ); + } + else + { + static struct timeval null_tv = { 0, 0 }; + + return( null_tv ); + } +} + +unsigned int Monitor::GetLastReadIndex() const +{ + return( shared_data->last_read_index!=image_buffer_count?shared_data->last_read_index:-1 ); +} + +unsigned int Monitor::GetLastWriteIndex() const +{ + return( shared_data->last_write_index!=image_buffer_count?shared_data->last_write_index:-1 ); +} + +unsigned int Monitor::GetLastEvent() const +{ + return( shared_data->last_event ); +} + +double Monitor::GetFPS() const +{ + int index1 = shared_data->last_write_index; + if ( index1 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap1 = &image_buffer[index1]; + if ( !snap1->timestamp || !snap1->timestamp->tv_sec ) + { + return( 0.0 ); + } + struct timeval time1 = *snap1->timestamp; + + int image_count = image_buffer_count; + int index2 = (index1+1)%image_buffer_count; + if ( index2 == image_buffer_count ) + { + return( 0.0 ); + } + Snapshot *snap2 = &image_buffer[index2]; + while ( !snap2->timestamp || !snap2->timestamp->tv_sec ) + { + if ( index1 == index2 ) + { + return( 0.0 ); + } + index2 = (index2+1)%image_buffer_count; + snap2 = &image_buffer[index2]; + image_count--; + } + struct timeval time2 = *snap2->timestamp; + + double time_diff = tvDiffSec( time2, time1 ); + + double curr_fps = image_count/time_diff; + + if ( curr_fps < 0.0 ) + { + //Error( "Negative FPS %f, time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", curr_fps, time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); + return( 0.0 ); + } + return( curr_fps ); +} + +void Monitor::ForceAlarmOn( int force_score, const char *force_cause, const char *force_text ) +{ + trigger_data->trigger_state = TRIGGER_ON; + trigger_data->trigger_score = force_score; + strncpy( trigger_data->trigger_cause, force_cause, sizeof(trigger_data->trigger_cause) ); + strncpy( trigger_data->trigger_text, force_text, sizeof(trigger_data->trigger_text) ); +} + +void Monitor::ForceAlarmOff() +{ + trigger_data->trigger_state = TRIGGER_OFF; +} + +void Monitor::CancelForced() +{ + trigger_data->trigger_state = TRIGGER_CANCEL; +} + +void Monitor::actionReload() +{ + shared_data->action |= RELOAD; +} + +void Monitor::actionEnable() +{ + shared_data->action |= RELOAD; + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 1 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +void Monitor::actionDisable() +{ + shared_data->action |= RELOAD; + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "update Monitors set Enabled = 0 where Id = '%d'", id ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +void Monitor::actionSuspend() +{ + shared_data->action |= SUSPEND; +} + +void Monitor::actionResume() +{ + shared_data->action |= RESUME; +} + +int Monitor::actionBrightness( int p_brightness ) +{ + if ( purpose != CAPTURE ) + { + if ( p_brightness >= 0 ) + { + shared_data->brightness = p_brightness; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set brightness" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get brightness" ); + return( -1 ); + } + } + } + return( shared_data->brightness ); + } + return( camera->Brightness( p_brightness ) ); +} + +int Monitor::actionContrast( int p_contrast ) +{ + if ( purpose != CAPTURE ) + { + if ( p_contrast >= 0 ) + { + shared_data->contrast = p_contrast; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set contrast" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get contrast" ); + return( -1 ); + } + } + } + return( shared_data->contrast ); + } + return( camera->Contrast( p_contrast ) ); +} + +int Monitor::actionHue( int p_hue ) +{ + if ( purpose != CAPTURE ) + { + if ( p_hue >= 0 ) + { + shared_data->hue = p_hue; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set hue" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get hue" ); + return( -1 ); + } + } + } + return( shared_data->hue ); + } + return( camera->Hue( p_hue ) ); +} + +int Monitor::actionColour( int p_colour ) +{ + if ( purpose != CAPTURE ) + { + if ( p_colour >= 0 ) + { + shared_data->colour = p_colour; + shared_data->action |= SET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & SET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to set colour" ); + return( -1 ); + } + } + } + else + { + shared_data->action |= GET_SETTINGS; + int wait_loops = 10; + while ( shared_data->action & GET_SETTINGS ) + { + if ( wait_loops-- ) + usleep( 100000 ); + else + { + Warning( "Timed out waiting to get colour" ); + return( -1 ); + } + } + } + return( shared_data->colour ); + } + return( camera->Colour( p_colour ) ); +} + +void Monitor::DumpZoneImage( const char *zone_string ) +{ + int exclude_id = 0; + int extra_colour = 0; + Polygon extra_zone; + + if ( zone_string ) + { + if ( !Zone::ParseZoneString( zone_string, exclude_id, extra_colour, extra_zone ) ) + { + Error( "Failed to parse zone string, ignoring" ); + } + } + + int index = shared_data->last_write_index; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + Image zone_image( *snap_image ); + if(zone_image.Colours() == ZM_COLOUR_GRAY8) { + zone_image.Colourise(ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB ); + } + + for( int i = 0; i < n_zones; i++ ) + { + if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zones[i]->Id() == exclude_id ) + continue; + + Rgb colour; + if ( exclude_id && !extra_zone.getNumCoords() && zones[i]->Id() == exclude_id ) + { + colour = extra_colour; + } + else + { + if ( zones[i]->IsActive() ) + { + colour = RGB_RED; + } + else if ( zones[i]->IsInclusive() ) + { + colour = RGB_ORANGE; + } + else if ( zones[i]->IsExclusive() ) + { + colour = RGB_PURPLE; + } + else if ( zones[i]->IsPreclusive() ) + { + colour = RGB_BLUE; + } + else + { + colour = RGB_WHITE; + } + } + zone_image.Fill( colour, 2, zones[i]->GetPolygon() ); + zone_image.Outline( colour, zones[i]->GetPolygon() ); + } + + if ( extra_zone.getNumCoords() ) + { + zone_image.Fill( extra_colour, 2, extra_zone ); + zone_image.Outline( extra_colour, extra_zone ); + } + + static char filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Zones%d.jpg", id ); + zone_image.WriteJpeg( filename ); +} + +void Monitor::DumpImage( Image *dump_image ) const +{ + if ( image_count && !(image_count%10) ) + { + static char filename[PATH_MAX]; + static char new_filename[PATH_MAX]; + snprintf( filename, sizeof(filename), "Monitor%d.jpg", id ); + snprintf( new_filename, sizeof(new_filename), "Monitor%d-new.jpg", id ); + dump_image->WriteJpeg( new_filename ); + rename( new_filename, filename ); + } +} + +bool Monitor::CheckSignal( const Image *image ) +{ + static bool static_undef = true; + /* RGB24 colors */ + static uint8_t red_val; + static uint8_t green_val; + static uint8_t blue_val; + static uint8_t grayscale_val; /* 8bit grayscale color */ + static Rgb colour_val; /* RGB32 color */ + static int usedsubpixorder; + + if ( config.signal_check_points > 0 ) + { + if ( static_undef ) + { + static_undef = false; + usedsubpixorder = camera->SubpixelOrder(); + colour_val = rgb_convert(signal_check_colour, ZM_SUBPIX_ORDER_BGR); /* HTML colour code is actually BGR in memory, we want RGB */ + colour_val = rgb_convert(colour_val, usedsubpixorder); + red_val = RED_VAL_BGRA(signal_check_colour); + green_val = GREEN_VAL_BGRA(signal_check_colour); + blue_val = BLUE_VAL_BGRA(signal_check_colour); + grayscale_val = signal_check_colour & 0xff; /* Clear all bytes but lowest byte */ + } + + const uint8_t *buffer = image->Buffer(); + int pixels = image->Pixels(); + int width = image->Width(); + int colours = image->Colours(); + + int index = 0; + for ( int i = 0; i < config.signal_check_points; i++ ) + { + while( true ) + { + index = (int)(((long long)rand()*(long long)(pixels-1))/RAND_MAX); + if ( !config.timestamp_on_capture || !label_format[0] ) + break; + // Avoid sampling the rows with timestamp in + if ( index < (label_coord.Y()*width) || index >= (label_coord.Y()+Image::LINE_HEIGHT)*width ) + break; + } + + if(colours == ZM_COLOUR_GRAY8) { + if ( *(buffer+index) != grayscale_val ) + return true; + + } else if(colours == ZM_COLOUR_RGB24) { + const uint8_t *ptr = buffer+(index*colours); + + if ( usedsubpixorder == ZM_SUBPIX_ORDER_BGR) { + if ( (RED_PTR_BGRA(ptr) != red_val) || (GREEN_PTR_BGRA(ptr) != green_val) || (BLUE_PTR_BGRA(ptr) != blue_val) ) + return true; + } else { + /* Assume RGB */ + if ( (RED_PTR_RGBA(ptr) != red_val) || (GREEN_PTR_RGBA(ptr) != green_val) || (BLUE_PTR_RGBA(ptr) != blue_val) ) + return true; + } + + } else if(colours == ZM_COLOUR_RGB32) { + if ( usedsubpixorder == ZM_SUBPIX_ORDER_ARGB || usedsubpixorder == ZM_SUBPIX_ORDER_ABGR) { + if ( ARGB_ABGR_ZEROALPHA(*(((const Rgb*)buffer)+index)) != ARGB_ABGR_ZEROALPHA(colour_val) ) + return true; + } else { + /* Assume RGBA or BGRA */ + if ( RGBA_BGRA_ZEROALPHA(*(((const Rgb*)buffer)+index)) != RGBA_BGRA_ZEROALPHA(colour_val) ) + return true; + } + } + + } + return( false ); + } + return( true ); +} + +bool Monitor::Analyse() +{ + if ( shared_data->last_read_index == shared_data->last_write_index ) + { + return( false ); + } + + struct timeval now; + gettimeofday( &now, NULL ); + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + fps = double(fps_report_interval)/(now.tv_sec-last_fps_time); + Info( "%s: %d - Processing at %.2f fps", name, image_count, fps ); + last_fps_time = now.tv_sec; + } + + int index; + if ( config.opt_adaptive_skip ) + { + int read_margin = shared_data->last_read_index - shared_data->last_write_index; + if ( read_margin < 0 ) read_margin += image_buffer_count; + + int step = 1; + if ( read_margin > 0 ) + { + step = (9*image_buffer_count)/(5*read_margin); + } + + int pending_frames = shared_data->last_write_index - shared_data->last_read_index; + if ( pending_frames < 0 ) pending_frames += image_buffer_count; + + Debug( 4, "RI:%d, WI: %d, PF = %d, RM = %d, Step = %d", shared_data->last_read_index, shared_data->last_write_index, pending_frames, read_margin, step ); + if ( step <= pending_frames ) + { + index = (shared_data->last_read_index+step)%image_buffer_count; + } + else + { + if ( pending_frames ) + { + Warning( "Approaching buffer overrun, consider slowing capture, simplifying analysis or increasing ring buffer size" ); + } + index = shared_data->last_write_index%image_buffer_count; + } + } + else + { + index = shared_data->last_write_index%image_buffer_count; + } + + Snapshot *snap = &image_buffer[index]; + struct timeval *timestamp = snap->timestamp; + Image *snap_image = snap->image; + + if ( shared_data->action ) + { + if ( shared_data->action & RELOAD ) + { + Info( "Received reload indication at count %d", image_count ); + shared_data->action &= ~RELOAD; + Reload(); + } + if ( shared_data->action & SUSPEND ) + { + if ( Active() ) + { + Info( "Received suspend indication at count %d", image_count ); + shared_data->active = false; + //closeEvent(); + } + if ( config.max_suspend_time ) + { + auto_resume_time = now.tv_sec + config.max_suspend_time; + } + shared_data->action &= ~SUSPEND; + } + if ( shared_data->action & RESUME ) + { + if ( Enabled() && !Active() ) + { + Info( "Received resume indication at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + shared_data->alarm_x = shared_data->alarm_y = -1; + } + shared_data->action &= ~RESUME; + } + } + if ( auto_resume_time && (now.tv_sec >= auto_resume_time) ) + { + Info( "Auto resuming at count %d", image_count ); + shared_data->active = true; + ref_image = *snap_image; + ready_count = image_count+(warmup_count/2); + auto_resume_time = 0; + } + + static bool static_undef = true; + static struct timeval **timestamps; + static Image **images; + static int last_section_mod = 0; + static bool last_signal; + + if ( static_undef ) + { + static_undef = false; + timestamps = new struct timeval *[pre_event_count]; + images = new Image *[pre_event_count]; + last_signal = shared_data->signal; + } + + if ( Enabled() ) + { + bool signal = shared_data->signal; + bool signal_change = (signal != last_signal); + if ( trigger_data->trigger_state != TRIGGER_OFF ) + { + unsigned int score = 0; + if ( Ready() ) + { + std::string cause; + Event::StringSetMap noteSetMap; + + if ( trigger_data->trigger_state == TRIGGER_ON ) + { + score += trigger_data->trigger_score; + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += trigger_data->trigger_cause; + } + Event::StringSet noteSet; + noteSet.insert( trigger_data->trigger_text ); + noteSetMap[trigger_data->trigger_cause] = noteSet; + } + if ( signal_change ) + { + const char *signalText; + if ( !signal ) + signalText = "Lost"; + else + { + signalText = "Reacquired"; + score += 100; + } + Warning( "%s: %s", SIGNAL_CAUSE, signalText ); + if ( event && !signal ) + { + Info( "%s: %03d - Closing event %d, signal loss", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + if ( !event ) + { + if ( cause.length() ) + cause += ", "; + cause += SIGNAL_CAUSE; + } + Event::StringSet noteSet; + noteSet.insert( signalText ); + noteSetMap[SIGNAL_CAUSE] = noteSet; + shared_data->state = state = IDLE; + shared_data->active = signal; + ref_image = *snap_image; + } + else if ( signal && Active() && (function == MODECT || function == MOCORD) ) + { + Event::StringSet zoneSet; + int motion_score = DetectMotion( *snap_image, zoneSet ); + if ( motion_score ) + { + if ( !event ) + { + score += motion_score; + if ( cause.length() ) + cause += ", "; + cause += MOTION_CAUSE; + } + else + { + score += motion_score; + } + noteSetMap[MOTION_CAUSE] = zoneSet; + } + shared_data->active = signal; + } + if ( (!signal_change && signal) && n_linked_monitors > 0 ) + { + bool first_link = true; + Event::StringSet noteSet; + for ( int i = 0; i < n_linked_monitors; i++ ) + { + if ( linked_monitors[i]->isConnected() ) + { + if ( linked_monitors[i]->hasAlarmed() ) + { + if ( !event ) + { + if ( first_link ) + { + if ( cause.length() ) + cause += ", "; + cause += LINKED_CAUSE; + first_link = false; + } + } + noteSet.insert( linked_monitors[i]->Name() ); + score += 50; + } + } + else + { + linked_monitors[i]->connect(); + } + } + if ( noteSet.size() > 0 ) + noteSetMap[LINKED_CAUSE] = noteSet; + } + if ( (!signal_change && signal) && (function == RECORD || function == MOCORD) ) + { + if ( event ) + { + int section_mod = timestamp->tv_sec%section_length; + if ( section_mod < last_section_mod ) + { + if ( state == IDLE || state == TAPE || event_close_mode == CLOSE_TIME ) + { + if ( state == TAPE ) + { + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, section end", name, image_count, event->Id() ) + } + else + Info( "%s: %03d - Closing event %d, section end forced ", name, image_count, event->Id() ); + closeEvent(); + last_section_mod = 0; + } + } + else + { + last_section_mod = section_mod; + } + } + if ( !event ) + { + + // Create event + event = new Event( this, *timestamp, "Continuous", noteSetMap ); + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, section start", name, image_count, event->Id() ); + + /* To prevent cancelling out an existing alert\prealarm\alarm state */ + if ( state == IDLE ) + { + shared_data->state = state = TAPE; + } + + //if ( config.overlap_timed_events ) + if ( false ) + { + int pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + int pre_event_images = pre_event_count; + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index+1)%image_buffer_count; + pre_event_images--; + } + + if ( pre_event_images ) + { + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_images, images, timestamps ); + } + } + } + } + if ( score ) + { + if ( (state == IDLE || state == TAPE || state == PREALARM ) ) + { + if ( Event::PreAlarmCount() >= (alarm_frame_count-1) ) + { + Info( "%s: %03d - Gone into alarm state", name, image_count ); + shared_data->state = state = ALARM; + if ( signal_change || (function != MOCORD && state != ALERT) ) + { + int pre_index; + if ( alarm_frame_count > 1 ) + pre_index = ((index+image_buffer_count)-((alarm_frame_count-1)+pre_event_count))%image_buffer_count; + else + pre_index = ((index+image_buffer_count)-pre_event_count)%image_buffer_count; + + int pre_event_images = pre_event_count; + while ( pre_event_images && !image_buffer[pre_index].timestamp->tv_sec ) + { + pre_index = (pre_index+1)%image_buffer_count; + pre_event_images--; + } + + event = new Event( this, *(image_buffer[pre_index].timestamp), cause, noteSetMap ); + shared_data->last_event = event->Id(); + + Info( "%s: %03d - Opening new event %d, alarm start", name, image_count, event->Id() ); + + if ( pre_event_images ) + { + for ( int i = 0; i < pre_event_images; i++ ) + { + timestamps[i] = image_buffer[pre_index].timestamp; + images[i] = image_buffer[pre_index].image; + + pre_index = (pre_index+1)%image_buffer_count; + } + event->AddFrames( pre_event_images, images, timestamps ); + } + if ( alarm_frame_count ) + { + event->SavePreAlarmFrames(); + } + } + } + else if ( state != PREALARM ) + { + Info( "%s: %03d - Gone into prealarm state", name, image_count ); + shared_data->state = state = PREALARM; + } + } + else if ( state == ALERT ) + { + Info( "%s: %03d - Gone back into alarm state", name, image_count ); + shared_data->state = state = ALARM; + } + last_alarm_count = image_count; + } + else + { + if ( state == ALARM ) + { + Info( "%s: %03d - Gone into alert state", name, image_count ); + shared_data->state = state = ALERT; + } + else if ( state == ALERT ) + { + if ( image_count-last_alarm_count > post_event_count ) + { + Info( "%s: %03d - Left alarm state (%d) - %d(%d) images", name, image_count, event->Id(), event->Frames(), event->AlarmFrames() ); + //if ( function != MOCORD || event_close_mode == CLOSE_ALARM || event->Cause() == SIGNAL_CAUSE ) + if ( function != MOCORD || event_close_mode == CLOSE_ALARM ) + { + shared_data->state = state = IDLE; + Info( "%s: %03d - Closing event %d, alarm end%s", name, image_count, event->Id(), (function==MOCORD)?", section truncated":"" ); + closeEvent(); + } + else + { + shared_data->state = state = TAPE; + } + } + } + if ( state == PREALARM ) + { + if ( function != MOCORD ) + { + shared_data->state = state = IDLE; + } + else + { + shared_data->state = state = TAPE; + } + } + if ( Event::PreAlarmCount() ) + Event::EmptyPreAlarmFrames(); + } + if ( state != IDLE ) + { + if ( state == PREALARM || state == ALARM ) + { + if ( config.create_analysis_images ) + { + bool got_anal_image = false; + Image alarm_image( *snap_image ); + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( zones[i]->AlarmImage() ) + { + alarm_image.Overlay( *(zones[i]->AlarmImage()) ); + got_anal_image = true; + } + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( got_anal_image ) + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score, &alarm_image ); + else + event->AddFrame( snap_image, *timestamp, score, &alarm_image ); + } + else + { + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + } + else + { + for( int i = 0; i < n_zones; i++ ) + { + if ( zones[i]->Alarmed() ) + { + if ( config.record_event_stats && state == ALARM ) + { + zones[i]->RecordStats( event ); + } + } + } + if ( state == PREALARM ) + Event::AddPreAlarmFrame( snap_image, *timestamp, score ); + else + event->AddFrame( snap_image, *timestamp, score ); + } + if ( event && noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == ALERT ) + { + event->AddFrame( snap_image, *timestamp ); + if ( noteSetMap.size() > 0 ) + event->updateNotes( noteSetMap ); + } + else if ( state == TAPE ) + { + if ( !(image_count%(frame_skip+1)) ) + { + if ( config.bulk_frame_interval > 1 ) + { + event->AddFrame( snap_image, *timestamp, (event->Frames()AddFrame( snap_image, *timestamp ); + } + } + } + } + } + } + else + { + if ( event ) + { + Info( "%s: %03d - Closing event %d, trigger off", name, image_count, event->Id() ); + closeEvent(); + } + shared_data->state = state = IDLE; + last_section_mod = 0; + } + if ( (!signal_change && signal) && (function == MODECT || function == MOCORD) && (config.blend_alarmed_images || state != ALARM) ) + { + ref_image.Blend( *snap_image, ref_blend_perc ); + } + last_signal = signal; + } + + shared_data->last_read_index = index%image_buffer_count; + //shared_data->last_read_time = image_buffer[index].timestamp->tv_sec; + shared_data->last_read_time = now.tv_sec; + image_count++; + + return( true ); +} + +void Monitor::Reload() +{ + Debug( 1, "Reloading monitor %s", name ); + + if ( event ) + Info( "%s: %03d - Closing event %d, reloading", name, image_count, event->Id() ); + + closeEvent(); + + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Function+0, Enabled, LinkedMonitors, EventPrefix, LabelFormat, LabelX, LabelY, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour 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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors != 1 ) + { + Error( "Bogus number of monitors, %d, returned. Can't reload", n_monitors ); + return; + } + + if ( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + int index = 0; + function = (Function)atoi(dbrow[index++]); + enabled = atoi(dbrow[index++]); + const char *p_linked_monitors = dbrow[index++]; + strncpy( event_prefix, dbrow[index++], sizeof(event_prefix) ); + strncpy( label_format, dbrow[index++], sizeof(label_format) ); + label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; + warmup_count = atoi(dbrow[index++]); + pre_event_count = atoi(dbrow[index++]); + post_event_count = atoi(dbrow[index++]); + alarm_frame_count = atoi(dbrow[index++]); + section_length = atoi(dbrow[index++]); + frame_skip = atoi(dbrow[index++]); + capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + alarm_capture_delay = (dbrow[index]&&atof(dbrow[index])>0.0)?int(DT_PREC_3/atof(dbrow[index])):0; index++; + fps_report_interval = atoi(dbrow[index++]); + ref_blend_perc = atoi(dbrow[index++]); + track_motion = atoi(dbrow[index++]); + if ( dbrow[index][0] == '#' ) + signal_check_colour = strtol(dbrow[index]+1,0,16); + else + signal_check_colour = strtol(dbrow[index],0,16); + index++; + + shared_data->state = state = IDLE; + shared_data->alarm_x = shared_data->alarm_y = -1; + if ( enabled ) + shared_data->active = true; + ready_count = image_count+warmup_count; + + ReloadLinkedMonitors( p_linked_monitors ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + mysql_free_result( result ); + + ReloadZones(); +} + +void Monitor::ReloadZones() +{ + Debug( 1, "Reloading zones for monitor %s", name ); + for( int i = 0; i < n_zones; i++ ) + { + delete zones[i]; + } + delete[] zones; + zones = 0; + n_zones = Zone::Load( this, zones ); + //DumpZoneImage(); +} + +void Monitor::ReloadLinkedMonitors( const char *p_linked_monitors ) +{ + Debug( 1, "Reloading linked monitors for monitor %s, '%s'", name, p_linked_monitors ); + if ( n_linked_monitors ) + { + for( int i = 0; i < n_linked_monitors; i++ ) + { + delete linked_monitors[i]; + } + delete[] linked_monitors; + linked_monitors = 0; + } + + n_linked_monitors = 0; + if ( p_linked_monitors ) + { + int n_link_ids = 0; + int link_ids[256]; + + char link_id_str[8]; + char *dest_ptr = link_id_str; + const char *src_ptr = p_linked_monitors; + while( 1 ) + { + dest_ptr = link_id_str; + while( *src_ptr >= '0' && *src_ptr <= '9' ) + { + if ( (dest_ptr-link_id_str) < (sizeof(link_id_str)-1) ) + { + *dest_ptr++ = *src_ptr++; + } + else + { + break; + } + } + // Add the link monitor + if ( dest_ptr != link_id_str ) + { + *dest_ptr = '\0'; + int link_id = atoi(link_id_str); + if ( link_id > 0 && link_id != id) + { + Debug( 3, "Found linked monitor id %d", link_id ); + int j; + for ( j = 0; j < n_link_ids; j++ ) + { + if ( link_ids[j] == link_id ) + break; + } + if ( j == n_link_ids ) // Not already found + { + link_ids[n_link_ids++] = link_id; + } + } + } + if ( !*src_ptr ) + break; + while( *src_ptr && (*src_ptr < '0' || *src_ptr > '9') ) + src_ptr++; + if ( !*src_ptr ) + break; + } + if ( n_link_ids > 0 ) + { + Debug( 1, "Linking to %d monitors", n_link_ids ); + linked_monitors = new MonitorLink *[n_link_ids]; + int count = 0; + for ( int i = 0; i < n_link_ids; i++ ) + { + Debug( 1, "Checking linked monitor %d", link_ids[i] ); + + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name from Monitors where Id = %d and Function != 'None' and Function != 'Monitor' and Enabled = 1", link_ids[i] ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + if ( n_monitors == 1 ) + { + MYSQL_ROW dbrow = mysql_fetch_row( result ); + Debug( 1, "Linking to monitor %d", link_ids[i] ); + linked_monitors[count++] = new MonitorLink( link_ids[i], dbrow[1] ); + } + else + { + Warning( "Can't link to monitor %d, invalid id, function or not enabled", link_ids[i] ); + } + mysql_free_result( result ); + } + n_linked_monitors = count; + } + } +} + +#if ZM_HAS_V4L +int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !device[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Method, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour 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 ) ); + } + + 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 ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + const char *method = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = new LocalCamera( + id, + device, + channel, + format, + method, + cam_width, + cam_height, + colours, + palette, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE, + extras + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // ZM_HAS_V4L + +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]; + if ( !protocol ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion 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, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = 0; + if ( protocol == "http" ) + { + camera = new RemoteCameraHttp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#if HAVE_LIBAVFORMAT + else if ( protocol == "rtsp" ) + { + camera = new RemoteCameraRtsp( + id, + method, + host, // Host + port, // Port + path, // Path + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + } +#endif // HAVE_LIBAVFORMAT + else + { + Fatal( "Unexpected remote camera protocol '%s'", protocol.c_str() ); + } + + monitors[i] = new Monitor( + id, + name.c_str(), + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, 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 ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +int Monitor::LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'File' and Path = '%s'", file ); + } + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FileCamera( + id, + path, // File + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} + +#if HAVE_LIBAVFORMAT +int Monitor::LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + if ( !file[0] ) + { + strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg'", sizeof(sql) ); + } + else + { + snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Ffmpeg' and Path = '%s'", file ); + } + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + delete[] monitors; + monitors = new Monitor *[n_monitors]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + const char *name = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + const char *linked_monitors = dbrow[col]; col++; + + const char *path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + /* int palette = atoi(dbrow[col]); */ col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + const char *event_prefix = dbrow[col]; col++; + const char *label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + Camera *camera = new FfmpegCamera( + id, + path, // File + cam_width, + cam_height, + colours, + brightness, + contrast, + hue, + colour, + purpose==CAPTURE + ); + + monitors[i] = new Monitor( + id, + name, + function, + enabled, + linked_monitors, + camera, + orientation, + deinterlacing, + event_prefix, + label_format, + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + RGB_WHITE, + purpose + ); + Zone **zones = 0; + int n_zones = Zone::Load( monitors[i], zones ); + monitors[i]->AddZones( n_zones, zones ); + Debug( 1, "Loaded monitor %d(%s), %d zones", id, name, n_zones ); + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( n_monitors ); +} +#endif // HAVE_LIBAVFORMAT + +Monitor *Monitor::Load( int id, bool load_zones, Purpose purpose ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id, Name, Type, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Protocol, Method, Host, Port, Path, Width, Height, Colours, Palette, Orientation+0, Deinterlacing, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, StreamReplayBuffer, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion, SignalCheckColour 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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + Monitor *monitor = 0; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int id = atoi(dbrow[col]); col++; + std::string name = dbrow[col]; col++; + std::string type = dbrow[col]; col++; + int function = atoi(dbrow[col]); col++; + int enabled = atoi(dbrow[col]); col++; + std::string linked_monitors = dbrow[col]; col++; + + std::string device = dbrow[col]; col++; + int channel = atoi(dbrow[col]); col++; + int format = atoi(dbrow[col]); col++; + + std::string protocol = dbrow[col]; col++; + std::string method = dbrow[col]; col++; + std::string host = dbrow[col]; col++; + std::string port = dbrow[col]; col++; + std::string path = dbrow[col]; col++; + + int width = atoi(dbrow[col]); col++; + int height = atoi(dbrow[col]); col++; + int colours = atoi(dbrow[col]); col++; + int palette = atoi(dbrow[col]); col++; + Orientation orientation = (Orientation)atoi(dbrow[col]); col++; + unsigned int deinterlacing = atoi(dbrow[col]); col++; + int brightness = atoi(dbrow[col]); col++; + int contrast = atoi(dbrow[col]); col++; + int hue = atoi(dbrow[col]); col++; + int colour = atoi(dbrow[col]); col++; + + std::string event_prefix = dbrow[col]; col++; + std::string label_format = dbrow[col]; col++; + + int label_x = atoi(dbrow[col]); col++; + int label_y = atoi(dbrow[col]); col++; + + int image_buffer_count = atoi(dbrow[col]); col++; + int warmup_count = atoi(dbrow[col]); col++; + int pre_event_count = atoi(dbrow[col]); col++; + int post_event_count = atoi(dbrow[col]); col++; + int stream_replay_buffer = atoi(dbrow[col]); col++; + int alarm_frame_count = atoi(dbrow[col]); col++; + int section_length = atoi(dbrow[col]); col++; + int frame_skip = atoi(dbrow[col]); 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 fps_report_interval = atoi(dbrow[col]); col++; + int ref_blend_perc = atoi(dbrow[col]); col++; + int track_motion = atoi(dbrow[col]); col++; + int signal_check_colour; + if ( dbrow[col][0] == '#' ) + signal_check_colour = strtol(dbrow[col]+1,0,16); + else + signal_check_colour = strtol(dbrow[col],0,16); + + int cam_width = ((orientation==ROTATE_90||orientation==ROTATE_270)?height:width); + int cam_height = ((orientation==ROTATE_90||orientation==ROTATE_270)?width:height); + + int extras = (deinterlacing>>24)&0xff; + + Camera *camera = 0; + if ( type == "Local" ) + { +#if ZM_HAS_V4L + camera = new LocalCamera( + id, + device.c_str(), + channel, + format, + 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, + 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(), + 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 + { + 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, + event_prefix.c_str(), + label_format.c_str(), + Coord( label_x, label_y ), + image_buffer_count, + warmup_count, + pre_event_count, + post_event_count, + stream_replay_buffer, + alarm_frame_count, + section_length, + frame_skip, + capture_delay, + alarm_capture_delay, + fps_report_interval, + ref_blend_perc, + track_motion, + signal_check_colour, + purpose + ); + + int n_zones = 0; + if ( load_zones ) + { + Zone **zones = 0; + n_zones = Zone::Load( monitor, zones ); + monitor->AddZones( n_zones, 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 ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + return( monitor ); +} + +int Monitor::Capture() +{ + static int FirstCapture = 1; + int captureResult; + + int index = image_count%image_buffer_count; + Image* capture_image = image_buffer[index].image; + + if ( (deinterlacing & 0xff) == 4) { + if ( FirstCapture != 1 ) { + /* Copy the next image into the shared memory */ + capture_image->CopyBuffer(*(next_buffer.image)); + } + + /* Capture a new next image */ + captureResult = camera->Capture(*(next_buffer.image)); + + if ( FirstCapture ) { + FirstCapture = 0; + return 0; + } + + } else { + /* Capture directly into image buffer, avoiding the need to memcpy() */ + captureResult = camera->Capture(*capture_image); + } + + if ( captureResult != 0 ) + { + // Unable to capture image for temporary reason + // Fake a signal loss image + capture_image->Fill( signal_check_colour ); + captureResult = 0; + } else { + captureResult = 1; + } + + if ( captureResult == 1 ) + { + + /* Deinterlacing */ + if ( (deinterlacing & 0xff) == 1 ) { + capture_image->Deinterlace_Discard(); + } else if ( (deinterlacing & 0xff) == 2 ) { + capture_image->Deinterlace_Linear(); + } else if ( (deinterlacing & 0xff) == 3 ) { + capture_image->Deinterlace_Blend(); + } else if ( (deinterlacing & 0xff) == 4 ) { + capture_image->Deinterlace_4Field( next_buffer.image, (deinterlacing>>8)&0xff ); + } else if ( (deinterlacing & 0xff) == 5 ) { + capture_image->Deinterlace_Blend_CustomRatio( (deinterlacing>>8)&0xff ); + } + + + if ( orientation != ROTATE_0 ) + { + switch ( orientation ) + { + case ROTATE_0 : + { + // No action required + break; + } + case ROTATE_90 : + case ROTATE_180 : + case ROTATE_270 : + { + capture_image->Rotate( (orientation-1)*90 ); + break; + } + case FLIP_HORI : + case FLIP_VERT : + { + capture_image->Flip( orientation==FLIP_HORI ); + break; + } + } + } + + } + if ( true ) { + + if ( capture_image->Size() != camera->ImageSize() ) + { + Error( "Captured image does not match expected size, check width, height and colour depth" ); + return( -1 ); + } + + if ( (index == shared_data->last_read_index) && (function > MONITOR) ) + { + Warning( "Buffer overrun at index %d, image %d, slow down capture, speed up analysis or increase ring buffer size", index, image_count ); + time_t now = time(0); + double approxFps = double(image_buffer_count)/double(now-image_buffer[index].timestamp->tv_sec); + time_t last_read_delta = now - shared_data->last_read_time; + if ( last_read_delta > (image_buffer_count/approxFps) ) + { + Warning( "Last image read from shared memory %ld seconds ago, zma may have gone away", last_read_delta ) + shared_data->last_read_index = image_buffer_count; + } + } + + gettimeofday( image_buffer[index].timestamp, NULL ); + if ( config.timestamp_on_capture ) + { + TimestampImage( capture_image, image_buffer[index].timestamp ); + } + shared_data->signal = CheckSignal(capture_image); + shared_data->last_write_index = index; + shared_data->last_write_time = image_buffer[index].timestamp->tv_sec; + + image_count++; + + if ( image_count && fps_report_interval && !(image_count%fps_report_interval) ) + { + time_t now = image_buffer[index].timestamp->tv_sec; + fps = double(fps_report_interval)/(now-last_fps_time); + //Info( "%d -> %d -> %d", fps_report_interval, now, last_fps_time ); + //Info( "%d -> %d -> %lf -> %lf", now-last_fps_time, fps_report_interval/(now-last_fps_time), double(fps_report_interval)/(now-last_fps_time), fps ); + Info( "%s: %d - Capturing at %.2lf fps", name, image_count, fps ); + last_fps_time = now; + } + + if ( shared_data->action & GET_SETTINGS ) + { + shared_data->brightness = camera->Brightness(); + shared_data->hue = camera->Hue(); + shared_data->colour = camera->Colour(); + shared_data->contrast = camera->Contrast(); + shared_data->action &= ~GET_SETTINGS; + } + if ( shared_data->action & SET_SETTINGS ) + { + camera->Brightness( shared_data->brightness ); + camera->Hue( shared_data->hue ); + camera->Colour( shared_data->colour ); + camera->Contrast( shared_data->contrast ); + shared_data->action &= ~SET_SETTINGS; + } + return( 0 ); + } + shared_data->signal = false; + return( -1 ); +} + +void Monitor::TimestampImage( Image *ts_image, const struct timeval *ts_time ) const +{ + if ( label_format[0] ) + { + // Expand the strftime macros first + char label_time_text[256]; + strftime( label_time_text, sizeof(label_time_text), label_format, localtime( &ts_time->tv_sec ) ); + + char label_text[1024]; + const char *s_ptr = label_time_text; + char *d_ptr = label_text; + while ( *s_ptr && ((d_ptr-label_text) < sizeof(label_text)) ) + { + if ( *s_ptr == '%' ) + { + bool found_macro = false; + switch ( *(s_ptr+1) ) + { + case 'N' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", name ); + found_macro = true; + break; + case 'Q' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%s", trigger_data->trigger_showtext ); + found_macro = true; + break; + case 'f' : + d_ptr += snprintf( d_ptr, sizeof(label_text)-(d_ptr-label_text), "%02ld", ts_time->tv_usec/10000 ); + found_macro = true; + break; + } + if ( found_macro ) + { + s_ptr += 2; + continue; + } + } + *d_ptr++ = *s_ptr++; + } + *d_ptr = '\0'; + ts_image->Annotate( label_text, label_coord ); + } +} + +bool Monitor::closeEvent() +{ + if ( event ) + { + if ( function == RECORD || function == MOCORD ) + { + gettimeofday( &(event->EndTime()), NULL ); + } + delete event; + event = 0; + return( true ); + } + return( false ); +} + +unsigned int Monitor::DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ) +{ + bool alarm = false; + unsigned int score = 0; + + if ( n_zones <= 0 ) return( alarm ); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-r.jpg", config.dir_events, id ); + } + ref_image.WriteJpeg( diag_path ); + } + + ref_image.Delta( comp_image, &delta_image); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-d.jpg", config.dir_events, id ); + } + delta_image.WriteJpeg( diag_path ); + } + + // Blank out all exclusion zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + zone->ClearAlarm(); + if ( !zone->IsInactive() ) + { + continue; + } + Debug( 3, "Blanking inactive zone %s", zone->Label() ); + delta_image.Fill( RGB_BLACK, zone->GetPolygon() ); + } + + // Check preclusive zones first + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsPreclusive() ) + { + continue; + } + Debug( 3, "Checking preclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + //zone->ResetStats(); + } + } + + Coord alarm_centre; + int top_score = -1; + + if ( alarm ) + { + alarm = false; + score = 0; + } + else + { + // Find all alarm pixels in active zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsActive() ) + { + continue; + } + Debug( 3, "Checking active zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( (int)zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } + + if ( alarm ) + { + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsInclusive() ) + { + continue; + } + Debug( 3, "Checking inclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + if ( config.opt_control && track_motion ) + { + if ( zone->Score() > top_score ) + { + top_score = zone->Score(); + alarm_centre = zone->GetAlarmCentre(); + } + } + } + } + } + else + { + // Find all alarm pixels in exclusive zones + for ( int n_zone = 0; n_zone < n_zones; n_zone++ ) + { + Zone *zone = zones[n_zone]; + if ( !zone->IsExclusive() ) + { + continue; + } + Debug( 3, "Checking exclusive zone %s", zone->Label() ); + if ( zone->CheckAlarms( &delta_image ) ) + { + alarm = true; + score += zone->Score(); + zone->SetAlarm(); + Debug( 3, "Zone is alarmed, zone score = %d", zone->Score() ); + zoneSet.insert( zone->Label() ); + } + } + } + } + + if ( top_score > 0 ) + { + shared_data->alarm_x = alarm_centre.X(); + shared_data->alarm_y = alarm_centre.Y(); + + Info( "Got alarm centre at %d,%d, at count %d", shared_data->alarm_x, shared_data->alarm_y, image_count ); + } + else + { + shared_data->alarm_x = shared_data->alarm_y = -1; + } + + // This is a small and innocent hack to prevent scores of 0 being returned in alarm state + return( score?score:alarm ); +} + +bool Monitor::DumpSettings( char *output, bool verbose ) +{ + output[0] = 0; + + sprintf( output+strlen(output), "Id : %d\n", id ); + sprintf( output+strlen(output), "Name : %s\n", name ); + sprintf( output+strlen(output), "Type : %s\n", camera->IsLocal()?"Local":(camera->IsRemote()?"Remote":"File") ); +#if ZM_HAS_V4L + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Device : %s\n", ((LocalCamera *)camera)->Device().c_str() ); + sprintf( output+strlen(output), "Channel : %d\n", ((LocalCamera *)camera)->Channel() ); + sprintf( output+strlen(output), "Standard : %d\n", ((LocalCamera *)camera)->Standard() ); + } + else +#endif // ZM_HAS_V4L + if ( camera->IsRemote() ) + { + sprintf( output+strlen(output), "Protocol : %s\n", ((RemoteCamera *)camera)->Protocol().c_str() ); + sprintf( output+strlen(output), "Host : %s\n", ((RemoteCamera *)camera)->Host().c_str() ); + sprintf( output+strlen(output), "Port : %s\n", ((RemoteCamera *)camera)->Port().c_str() ); + sprintf( output+strlen(output), "Path : %s\n", ((RemoteCamera *)camera)->Path().c_str() ); + } + else if ( camera->IsFile() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FileCamera *)camera)->Path() ); + } +#if HAVE_LIBAVFORMAT + else if ( camera->IsFfmpeg() ) + { + sprintf( output+strlen(output), "Path : %s\n", ((FfmpegCamera *)camera)->Path().c_str() ); + } +#endif // HAVE_LIBAVFORMAT + sprintf( output+strlen(output), "Width : %d\n", camera->Width() ); + sprintf( output+strlen(output), "Height : %d\n", camera->Height() ); +#if ZM_HAS_V4L + if ( camera->IsLocal() ) + { + sprintf( output+strlen(output), "Palette : %d\n", ((LocalCamera *)camera)->Palette() ); + } +#endif // ZM_HAS_V4L + sprintf( output+strlen(output), "Colours : %d\n", camera->Colours() ); + sprintf( output+strlen(output), "Subpixel Order : %d\n", camera->SubpixelOrder() ); + sprintf( output+strlen(output), "Event Prefix : %s\n", event_prefix ); + sprintf( output+strlen(output), "Label Format : %s\n", label_format ); + sprintf( output+strlen(output), "Label Coord : %d,%d\n", label_coord.X(), label_coord.Y() ); + sprintf( output+strlen(output), "Image Buffer Count : %d\n", image_buffer_count ); + sprintf( output+strlen(output), "Warmup Count : %d\n", warmup_count ); + sprintf( output+strlen(output), "Pre Event Count : %d\n", pre_event_count ); + sprintf( output+strlen(output), "Post Event Count : %d\n", post_event_count ); + sprintf( output+strlen(output), "Stream Replay Buffer : %d\n", stream_replay_buffer ); + sprintf( output+strlen(output), "Alarm Frame Count : %d\n", alarm_frame_count ); + sprintf( output+strlen(output), "Section Length : %d\n", section_length ); + sprintf( output+strlen(output), "Maximum FPS : %.2f\n", capture_delay?DT_PREC_3/capture_delay:0.0 ); + sprintf( output+strlen(output), "Alarm Maximum FPS : %.2f\n", alarm_capture_delay?DT_PREC_3/alarm_capture_delay:0.0 ); + sprintf( output+strlen(output), "Reference Blend %%ge : %d\n", ref_blend_perc ); + sprintf( output+strlen(output), "Track Motion : %d\n", track_motion ); + sprintf( output+strlen(output), "Function: %d - %s\n", function, + function==NONE?"None":( + function==MONITOR?"Monitor Only":( + function==MODECT?"Motion Detection":( + function==RECORD?"Continuous Record":( + function==MOCORD?"Continuous Record with Motion Detection":( + function==NODECT?"Externally Triggered only, no Motion Detection":"Unknown" + )))))); + sprintf( output+strlen(output), "Zones : %d\n", n_zones ); + for ( int i = 0; i < n_zones; i++ ) + { + zones[i]->DumpSettings( output+strlen(output), verbose ); + } + return( true ); +} + +bool MonitorStream::checkSwapPath( const char *path, bool create_path ) +{ + uid_t uid = getuid(); + gid_t gid = getgid(); + + struct stat stat_buf; + if ( stat( path, &stat_buf ) < 0 ) + { + if ( create_path && errno == ENOENT ) + { + Debug( 3, "Swap path '%s' missing, creating", path ); + if ( mkdir( path, 0755 ) ) + { + Error( "Can't mkdir %s: %s", path, strerror(errno)); + return( false ); + } + if ( stat( path, &stat_buf ) < 0 ) + { + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); + } + } + else + { + Error( "Can't stat '%s': %s", path, strerror(errno) ); + return( false ); + } + } + if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", path ); + return( false ); + } + + mode_t mask = 0; + if ( uid == stat_buf.st_uid ) + { + // If we are the owner + mask = 00700; + } + else if ( gid == stat_buf.st_gid ) + { + // If we are in the owner group + mask = 00070; + } + else + { + // We are neither the owner nor in the group + mask = 00007; + } + + if ( (stat_buf.st_mode & mask) != mask ) + { + Error( "Insufficient permissions on swap image path '%s'", path ); + return( false ); + } + return( true ); +} + +void MonitorStream::processCommand( const CmdMsg *msg ) +{ + Debug( 2, "Got message, type %d, msg %d", msg->msg_type, msg->msg_data[0] ); + // Check for incoming command + switch( (MsgCommand)msg->msg_data[0] ) + { + case CMD_PAUSE : + { + Debug( 1, "Got PAUSE command" ); + + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + last_frame_sent = TV_2_FLOAT( now ); + break; + } + case CMD_PLAY : + { + Debug( 1, "Got PLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ZM_RATE_BASE; + break; + } + case CMD_VARPLAY : + { + Debug( 1, "Got VARPLAY command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + replay_rate = ntohs(((unsigned char)msg->msg_data[2]<<8)|(unsigned char)msg->msg_data[1])-32768; + break; + } + case CMD_STOP : + { + Debug( 1, "Got STOP command" ); + + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + break; + } + case CMD_FASTFWD : + { + Debug( 1, "Got FAST FWD command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case 2 * ZM_RATE_BASE : + replay_rate = 5 * ZM_RATE_BASE; + break; + case 5 * ZM_RATE_BASE : + replay_rate = 10 * ZM_RATE_BASE; + break; + case 10 * ZM_RATE_BASE : + replay_rate = 25 * ZM_RATE_BASE; + break; + case 25 * ZM_RATE_BASE : + case 50 * ZM_RATE_BASE : + replay_rate = 50 * ZM_RATE_BASE; + break; + default : + replay_rate = 2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_SLOWFWD : + { + Debug( 1, "Got SLOW FWD command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = 1; + break; + } + case CMD_SLOWREV : + { + Debug( 1, "Got SLOW REV command" ); + // Set paused flag + paused = true; + // Set delayed flag + delayed = true; + // Set play rate + replay_rate = ZM_RATE_BASE; + // Set step + step = -1; + break; + } + case CMD_FASTREV : + { + Debug( 1, "Got FAST REV command" ); + if ( paused ) + { + // Clear paused flag + paused = false; + // Set delayed_play flag + delayed = true; + } + // Set play rate + switch ( replay_rate ) + { + case -2 * ZM_RATE_BASE : + replay_rate = -5 * ZM_RATE_BASE; + break; + case -5 * ZM_RATE_BASE : + replay_rate = -10 * ZM_RATE_BASE; + break; + case -10 * ZM_RATE_BASE : + replay_rate = -25 * ZM_RATE_BASE; + break; + case -25 * ZM_RATE_BASE : + case -50 * ZM_RATE_BASE : + replay_rate = -50 * ZM_RATE_BASE; + break; + default : + replay_rate = -2 * ZM_RATE_BASE; + break; + } + break; + } + case CMD_ZOOMIN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got ZOOM IN command, to %d,%d", x, y ); + switch ( zoom ) + { + case 100: + zoom = 150; + break; + case 150: + zoom = 200; + break; + case 200: + zoom = 300; + break; + case 300: + zoom = 400; + break; + case 400: + default : + zoom = 500; + break; + } + break; + } + case CMD_ZOOMOUT : + { + Debug( 1, "Got ZOOM OUT command" ); + switch ( zoom ) + { + case 500: + zoom = 400; + break; + case 400: + zoom = 300; + break; + case 300: + zoom = 200; + break; + case 200: + zoom = 150; + break; + case 150: + default : + zoom = 100; + break; + } + break; + } + case CMD_PAN : + { + x = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + y = ((unsigned char)msg->msg_data[3]<<8)|(unsigned char)msg->msg_data[4]; + Debug( 1, "Got PAN command, to %d,%d", x, y ); + break; + } + case CMD_SCALE : + { + scale = ((unsigned char)msg->msg_data[1]<<8)|(unsigned char)msg->msg_data[2]; + Debug( 1, "Got SCALE command, to %d", scale ); + break; + } + case CMD_QUERY : + { + Debug( 1, "Got QUERY command, sending STATUS" ); + break; + } + default : + { + Error( "Got unexpected command %d", msg->msg_data[0] ); + break; + } + } + + struct { + int id; + int state; + double fps; + int buffer_level; + int rate; + double delay; + int zoom; + bool delayed; + bool paused; + bool enabled; + bool forced; + } status_data; + + status_data.id = monitor->Id(); + status_data.fps = monitor->GetFPS(); + status_data.state = monitor->shared_data->state; + if ( playback_buffer > 0 ) + status_data.buffer_level = (MOD_ADD( (temp_write_index-temp_read_index), 0, temp_image_buffer_count )*100)/temp_image_buffer_count; + else + status_data.buffer_level = 0; + status_data.delayed = delayed; + status_data.paused = paused; + status_data.rate = replay_rate; + status_data.delay = TV_2_FLOAT( now ) - TV_2_FLOAT( last_frame_timestamp ); + status_data.zoom = zoom; + //status_data.enabled = monitor->shared_data->active; + status_data.enabled = monitor->trigger_data->trigger_state!=Monitor::TRIGGER_OFF; + status_data.forced = monitor->trigger_data->trigger_state==Monitor::TRIGGER_ON; + Debug( 2, "L:%d, D:%d, P:%d, R:%d, d:%.3f, Z:%d, E:%d F:%d", + status_data.buffer_level, + status_data.delayed, + status_data.paused, + status_data.rate, + status_data.delay, + status_data.zoom, + status_data.enabled, + status_data.forced + ); + + DataMsg status_msg; + status_msg.msg_type = MSG_DATA_WATCH; + memcpy( &status_msg.msg_data, &status_data, sizeof(status_msg.msg_data) ); + int nbytes = 0; + if ( (nbytes = sendto( sd, &status_msg, sizeof(status_msg), MSG_DONTWAIT, (sockaddr *)&rem_addr, sizeof(rem_addr) )) < 0 ) + { + //if ( errno != EAGAIN ) + { + Error( "Can't sendto on sd %d: %s", sd, strerror(errno) ); + //exit( -1 ); + } + } + + updateFrameRate( monitor->GetFPS() ); +} + +bool MonitorStream::sendFrame( const char *filepath, struct timeval *timestamp ) +{ + bool send_raw = ((scale>=ZM_SCALE_BASE)&&(zoom==ZM_SCALE_BASE)); + + if ( type != STREAM_JPEG ) + send_raw = false; + if ( !config.timestamp_on_capture && timestamp ) + send_raw = false; + + if ( !send_raw ) + { + Image temp_image( filepath ); + + return( sendFrame( &temp_image, timestamp ) ); + } + else + { + int img_buffer_size = 0; + static unsigned char img_buffer[ZM_MAX_IMAGE_SIZE]; + + FILE *fdj = NULL; + if ( (fdj = fopen( filepath, "r" )) ) + { + img_buffer_size = fread( img_buffer, 1, sizeof(img_buffer), fdj ); + fclose( fdj ); + } + else + { + Error( "Can't open %s: %s", filepath, strerror(errno) ); + return( false ); + } + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 2; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + + last_frame_sent = TV_2_FLOAT( now ); + + return( true ); + } + return( false ); +} + +bool MonitorStream::sendFrame( Image *image, struct timeval *timestamp ) +{ + Image *send_image = prepareImage( image ); + if ( !config.timestamp_on_capture && timestamp ) + monitor->TimestampImage( send_image, timestamp ); + +#if HAVE_LIBAVCODEC + if ( type == STREAM_MPEG ) + { + if ( !vid_stream ) + { + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, send_image->Colours(), send_image->SubpixelOrder(), send_image->Width(), send_image->Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); + } + static struct timeval base_time; + struct DeltaTimeval delta_time; + if ( !frame_count ) + base_time = *timestamp; + DELTA_TIMEVAL( delta_time, *timestamp, base_time, DT_PREC_3 ); + /* double pts = */ vid_stream->EncodeFrame( send_image->Buffer(), send_image->Size(), config.mpeg_timed_frames, delta_time.delta ); + } + else +#endif // HAVE_LIBAVCODEC + { + static unsigned char temp_img_buffer[ZM_MAX_IMAGE_SIZE]; + + int img_buffer_size = 0; + unsigned char *img_buffer = temp_img_buffer; + + // Calculate how long it takes to actually send the frame + struct timeval frameStartTime; + gettimeofday( &frameStartTime, NULL ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + switch( type ) + { + case STREAM_JPEG : + send_image->EncodeJpeg( img_buffer, &img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n" ); + break; + case STREAM_RAW : + fprintf( stdout, "Content-Type: image/x-rgb\r\n" ); + img_buffer = (uint8_t*)send_image->Buffer(); + img_buffer_size = send_image->Size(); + break; + case STREAM_ZIP : + fprintf( stdout, "Content-Type: image/x-rgbz\r\n" ); + unsigned long zip_buffer_size; + send_image->Zip( img_buffer, &zip_buffer_size ); + img_buffer_size = zip_buffer_size; + break; + default : + Fatal( "Unexpected frame type %d", type ); + break; + } + fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size ); + if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 ) + { + if ( !zm_terminate ) + Error( "Unable to send stream frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + + struct timeval frameEndTime; + gettimeofday( &frameEndTime, NULL ); + + int frameSendTime = tvDiffMsec( frameStartTime, frameEndTime ); + if ( frameSendTime > 1000/maxfps ) + { + maxfps /= 1.5; + Error( "Frame send time %d msec too slow, throttling maxfps to %.2f", frameSendTime, maxfps ); + } + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); +} + +void MonitorStream::runStream() +{ + if ( type == STREAM_SINGLE ) + { + // Not yet migrated over to stream class + monitor->SingleImage( scale ); + return; + } + + openComms(); + + checkInitialised(); + + updateFrameRate( monitor->GetFPS() ); + + if ( type == STREAM_JPEG ) + fprintf( stdout, "Content-Type: multipart/x-mixed-replace;boundary=ZoneMinderFrame\r\n\r\n" ); + + int last_read_index = monitor->image_buffer_count; + + time_t stream_start_time; + time( &stream_start_time ); + + frame_count = 0; + + temp_image_buffer = 0; + temp_image_buffer_count = playback_buffer; + temp_read_index = temp_image_buffer_count; + temp_write_index = temp_image_buffer_count; + + char swap_path[PATH_MAX] = ""; + bool buffered_playback = false; + + if ( connkey && playback_buffer > 0 ) + { + Debug( 2, "Checking swap image location" ); + Debug( 3, "Checking swap image path" ); + strncpy( swap_path, config.path_swap, sizeof(swap_path) ); + if ( checkSwapPath( swap_path, false ) ) + { + snprintf( &(swap_path[strlen(swap_path)]), sizeof(swap_path)-strlen(swap_path), "/zmswap-m%d", monitor->Id() ); + if ( checkSwapPath( swap_path, true ) ) + { + snprintf( &(swap_path[strlen(swap_path)]), sizeof(swap_path)-strlen(swap_path), "/zmswap-q%06d", connkey ); + if ( checkSwapPath( swap_path, true ) ) + { + buffered_playback = true; + } + } + } + + if ( !buffered_playback ) + { + Error( "Unable to validate swap image path, disabling buffered playback" ); + } + else + { + Debug( 2, "Assigning temporary buffer" ); + temp_image_buffer = new SwapImage[temp_image_buffer_count]; + memset( temp_image_buffer, 0, sizeof(*temp_image_buffer)*temp_image_buffer_count ); + Debug( 2, "Assigned temporary buffer" ); + } + } + + float max_secs_since_last_sent_frame = 10.0; //should be > keep alive amount (5 secs) + while ( !zm_terminate ) + { + bool got_command = false; + if ( feof( stdout ) || ferror( stdout ) || !monitor->ShmValid() ) + { + break; + } + + gettimeofday( &now, NULL ); + + if ( connkey ) + { + while(checkCommandQueue()) { + got_command = true; + } + } + + bool frame_sent = false; + if ( buffered_playback && delayed ) + { + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Debug( 1, "Exceeded temporary streaming buffer" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + else + { + if ( !paused ) + { + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); + //Debug( 3, "tri: %d, ti: %d", temp_read_index, temp_index ); + SwapImage *swap_image = &temp_image_buffer[temp_index]; + + if ( !swap_image->valid ) + { + paused = true; + delayed = true; + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>=0?-1:1), temp_image_buffer_count ); + } + else + { + //Debug( 3, "siT: %f, lfT: %f", TV_2_FLOAT( swap_image->timestamp ), TV_2_FLOAT( last_frame_timestamp ) ); + double expected_delta_time = ((TV_2_FLOAT( swap_image->timestamp ) - TV_2_FLOAT( last_frame_timestamp )) * ZM_RATE_BASE)/replay_rate; + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + + //Debug( 3, "eDT: %.3lf, aDT: %.3f, lFS:%.3f, NOW:%.3f", expected_delta_time, actual_delta_time, last_frame_sent, TV_2_FLOAT( now ) ); + // If the next frame is due + if ( actual_delta_time > expected_delta_time ) + { + //Debug( 2, "eDT: %.3lf, aDT: %.3f", expected_delta_time, actual_delta_time ); + if ( temp_index%frame_mod == 0 ) + { + Debug( 2, "Sending delayed frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + frame_sent = true; + } + temp_read_index = MOD_ADD( temp_read_index, (replay_rate>0?1:-1), temp_image_buffer_count ); + } + } + } + else if ( step != 0 ) + { + temp_read_index = MOD_ADD( temp_read_index, (step>0?1:-1), temp_image_buffer_count ); + + SwapImage *swap_image = &temp_image_buffer[temp_read_index]; + + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_read_index].file_name, &temp_image_buffer[temp_read_index].timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, &(swap_image->timestamp), sizeof(last_frame_timestamp) ); + frame_sent = true; + step = 0; + } + else + { + int temp_index = MOD_ADD( temp_read_index, 0, temp_image_buffer_count ); + + double actual_delta_time = TV_2_FLOAT( now ) - last_frame_sent; + if ( got_command || actual_delta_time > 5 ) + { + // Send keepalive + Debug( 2, "Sending keepalive frame %d", temp_index ); + // Send the next frame + if ( !sendFrame( temp_image_buffer[temp_index].file_name, &temp_image_buffer[temp_index].timestamp ) ) + zm_terminate = true; + frame_sent = true; + } + } + } + if ( temp_read_index == temp_write_index ) + { + // Go back to live viewing + Warning( "Rewound over write index, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + } + if ( last_read_index != monitor->shared_data->last_write_index ) + { + int index = monitor->shared_data->last_write_index%monitor->image_buffer_count; + last_read_index = monitor->shared_data->last_write_index; + //Debug( 1, "%d: %x - %x", index, image_buffer[index].image, image_buffer[index].image->buffer ); + if ( (frame_mod == 1) || ((frame_count%frame_mod) == 0) ) + { + if ( !paused && !delayed ) + { + // Send the next frame + Monitor::Snapshot *snap = &monitor->image_buffer[index]; + + if ( !sendFrame( snap->image, snap->timestamp ) ) + zm_terminate = true; + memcpy( &last_frame_timestamp, snap->timestamp, sizeof(last_frame_timestamp) ); + frame_sent = true; + + temp_read_index = temp_write_index; + } + } + if ( buffered_playback ) + { + if ( monitor->shared_data->valid ) + { + if ( monitor->image_buffer[index].timestamp->tv_sec ) + { + int temp_index = temp_write_index%temp_image_buffer_count; + Debug( 2, "Storing frame %d", temp_index ); + if ( !temp_image_buffer[temp_index].valid ) + { + snprintf( temp_image_buffer[temp_index].file_name, sizeof(temp_image_buffer[0].file_name), "%s/zmswap-i%05d.jpg", swap_path, temp_index ); + temp_image_buffer[temp_index].valid = true; + } + memcpy( &(temp_image_buffer[temp_index].timestamp), monitor->image_buffer[index].timestamp, sizeof(temp_image_buffer[0].timestamp) ); + monitor->image_buffer[index].image->WriteJpeg( temp_image_buffer[temp_index].file_name, config.jpeg_file_quality ); + temp_write_index = MOD_ADD( temp_write_index, 1, temp_image_buffer_count ); + if ( temp_write_index == temp_read_index ) + { + // Go back to live viewing + Warning( "Exceeded temporary buffer, resuming live play" ); + // Clear paused flag + paused = false; + // Clear delayed_play flag + delayed = false; + replay_rate = ZM_RATE_BASE; + } + } + else + { + Warning( "Unable to store frame as timestamp invalid" ); + } + } + else + { + Warning( "Unable to store frame as shared memory invalid" ); + } + } + frame_count++; + } + usleep( (unsigned long)((1000000 * ZM_RATE_BASE)/((base_fps?base_fps:1)*abs(replay_rate*2))) ); + if ( ttl ) + { + if ( (now.tv_sec - stream_start_time) > ttl ) + { + break; + } + } + if ( (TV_2_FLOAT( now ) - last_frame_sent) > max_secs_since_last_sent_frame ) + { + Error( "Terminating, last frame sent time %f secs more than maximum of %f", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame ); + break; + } + } + if ( buffered_playback ) + { + char swap_path[PATH_MAX] = ""; + + snprintf( swap_path, sizeof(swap_path), "%s/zmswap-m%d/zmswap-q%06d", config.path_swap, monitor->Id(), connkey ); + Debug( 1, "Cleaning swap files from %s", swap_path ); + struct stat stat_buf; + if ( stat( swap_path, &stat_buf ) < 0 ) + { + if ( errno != ENOENT ) + { + Error( "Can't stat '%s': %s", swap_path, strerror(errno) ); + } + } + else if ( !S_ISDIR(stat_buf.st_mode) ) + { + Error( "Swap image path '%s' is not a directory", swap_path ); + } + else + { + char glob_pattern[PATH_MAX] = ""; + + snprintf( glob_pattern, sizeof(glob_pattern), "%s/*.*", swap_path ); + glob_t pglob; + int glob_status = glob( glob_pattern, 0, 0, &pglob ); + if ( glob_status != 0 ) + { + if ( glob_status < 0 ) + { + Error( "Can't glob '%s': %s", glob_pattern, strerror(errno) ); + } + else + { + Debug( 1, "Can't glob '%s': %d", glob_pattern, glob_status ); + } + } + else + { + for ( int i = 0; i < pglob.gl_pathc; i++ ) + { + if ( unlink( pglob.gl_pathv[i] ) < 0 ) + { + Error( "Can't unlink '%s': %s", pglob.gl_pathv[i], strerror(errno) ); + } + } + } + globfree( &pglob ); + if ( rmdir( swap_path ) < 0 ) + { + Error( "Can't rmdir '%s': %s", swap_path, strerror(errno) ); + } + } + } + closeComms(); +} + +void Monitor::SingleImage( int scale) +{ + int img_buffer_size = 0; + static JOCTET img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->EncodeJpeg( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); +} + +void Monitor::SingleImageRaw( int scale) +{ + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + + fprintf( stdout, "Content-Length: %d\r\n", snap_image->Size() ); + fprintf( stdout, "Content-Type: image/x-rgb\r\n\r\n" ); + fwrite( snap_image->Buffer(), snap_image->Size(), 1, stdout ); +} + +void Monitor::SingleImageZip( int scale) +{ + unsigned long img_buffer_size = 0; + static Bytef img_buffer[ZM_MAX_IMAGE_SIZE]; + Image scaled_image; + int index = shared_data->last_write_index%image_buffer_count; + Snapshot *snap = &image_buffer[index]; + Image *snap_image = snap->image; + + if ( scale != ZM_SCALE_BASE ) + { + scaled_image.Assign( *snap_image ); + scaled_image.Scale( scale ); + snap_image = &scaled_image; + } + if ( !config.timestamp_on_capture ) + { + TimestampImage( snap_image, snap->timestamp ); + } + snap_image->Zip( img_buffer, &img_buffer_size ); + + fprintf( stdout, "Content-Length: %ld\r\n", img_buffer_size ); + fprintf( stdout, "Content-Type: image/x-rgbz\r\n\r\n" ); + fwrite( img_buffer, img_buffer_size, 1, stdout ); +} diff --git a/src/zm_monitor.h b/src/zm_monitor.h new file mode 100644 index 000000000..8fdcea8cd --- /dev/null +++ b/src/zm_monitor.h @@ -0,0 +1,477 @@ +// +// ZoneMinder Monitor Class Interfaces, $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. +// + +#ifndef ZM_MONITOR_H +#define ZM_MONITOR_H + +#include +#include + + +#include "zm.h" +#include "zm_coord.h" +#include "zm_image.h" +#include "zm_rgb.h" +#include "zm_zone.h" +#include "zm_event.h" +#include "zm_camera.h" +#include "zm_plugin_manager.h" +#include "zm_image_analyser.h" + +#include +#include + +#define SIGNAL_CAUSE "Signal" +#define MOTION_CAUSE "Motion" +#define LINKED_CAUSE "Linked" + +// +// This is the main class for monitors. Each monitor is associated +// with a camera and is effectively a collector for events. +// +class Monitor +{ +friend class MonitorStream; + +public: + typedef enum + { + QUERY=0, + CAPTURE, + ANALYSIS + } Purpose; + + typedef enum + { + NONE=1, + MONITOR, + MODECT, + RECORD, + MOCORD, + NODECT + } Function; + + typedef enum + { + ROTATE_0=1, + ROTATE_90, + ROTATE_180, + ROTATE_270, + FLIP_HORI, + FLIP_VERT + } Orientation; + + typedef enum + { + IDLE, + PREALARM, + ALARM, + ALERT, + TAPE + } State; + +protected: + typedef std::set ZoneSet; + + typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action; + + typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode; + + /* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */ + typedef struct + { + uint32_t size; /* +0 */ + uint32_t last_write_index; /* +4 */ + uint32_t last_read_index; /* +8 */ + uint32_t state; /* +12 */ + uint32_t last_event; /* +16 */ + uint32_t action; /* +20 */ + int32_t brightness; /* +24 */ + int32_t hue; /* +28 */ + int32_t colour; /* +32 */ + int32_t contrast; /* +36 */ + int32_t alarm_x; /* +40 */ + int32_t alarm_y; /* +44 */ + uint8_t valid; /* +48 */ + uint8_t active; /* +49 */ + uint8_t signal; /* +50 */ + uint8_t format; /* +51 */ + uint32_t imagesize; /* +52 */ + uint32_t epadding1; /* +56 */ + uint32_t epadding2; /* +60 */ + /* + ** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038. + ** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16. + */ + union { /* +64 */ + time_t last_write_time; + uint64_t extrapad1; + }; + union { /* +72 */ + time_t last_read_time; + uint64_t extrapad2; + }; + uint8_t control_state[256]; /* +80 */ + + } SharedData; + + typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState; + + /* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */ + typedef struct + { + uint32_t size; + uint32_t trigger_state; + uint32_t trigger_score; + uint32_t padding; + char trigger_cause[32]; + char trigger_text[256]; + char trigger_showtext[256]; + } TriggerData; + + /* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */ + struct Snapshot + { + struct timeval *timestamp; + Image *image; + void* padding; + }; + + //========================================================================= + PluginManager ThePluginManager; + std::vector m_sPluginNames; + //int iDoNativeMotDet; + + + class MonitorLink + { + protected: + unsigned int id; + char name[64]; + + bool connected; + time_t last_connect_time; + +#if ZM_MEM_MAPPED + int map_fd; + char mem_file[PATH_MAX]; +#else // ZM_MEM_MAPPED + int shm_id; +#endif // ZM_MEM_MAPPED + int mem_size; + unsigned char *mem_ptr; + + volatile SharedData *shared_data; + volatile TriggerData *trigger_data; + + int last_state; + int last_event; + + public: + MonitorLink( int p_id, const char *p_name ); + ~MonitorLink(); + + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } + + inline bool isConnected() const + { + return( connected ); + } + inline time_t getLastConnectTime() const + { + return( last_connect_time ); + } + + bool connect(); + bool disconnect(); + + bool isAlarmed(); + bool inAlarm(); + bool hasAlarmed(); + }; + +protected: + // These are read from the DB and thereafter remain unchanged + unsigned int id; + char name[64]; + Function function; // What the monitor is doing + 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 height; // Normally the same as the camera, but not if partly rotated + Orientation orientation; // Whether the image has to be rotated at all + unsigned int deinterlacing; + int brightness; // The statically saved brightness of the camera + int contrast; // The statically saved contrast of the camera + int hue; // The statically saved hue of the camera + int colour; // The statically saved colour of the camera + char event_prefix[64]; // The prefix applied to event names as they are created + char label_format[64]; // The format of the timestamp on the images + Coord label_coord; // The coordinates of the timestamp on the images + int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count + int warmup_count; // How many images to process before looking for events + int pre_event_count; // How many images to hold and prepend to an alarm event + int post_event_count; // How many unalarmed images must occur before the alarm state is reset + int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now + int section_length; // How long events should last in continuous modes + int frame_skip; // How many frames to skip in continuous modes + int capture_delay; // How long we wait between capture frames + int alarm_capture_delay; // How long we wait between capture frames when in alarm state + int alarm_frame_count; // How many alarm frames are required before an event is triggered + int fps_report_interval; // How many images should be captured/processed between reporting the current FPS + int ref_blend_perc; // Percentage of new image going into reference image. + bool track_motion; // Whether this monitor tries to track detected motion + Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected + + double fps; + Image delta_image; + Image ref_image; + + Purpose purpose; // What this monitor has been created to do + int event_count; + int image_count; + int ready_count; + int first_alarm_count; + int last_alarm_count; + int buffer_count; + int prealarm_count; + State state; + time_t start_time; + time_t last_fps_time; + time_t auto_resume_time; + + EventCloseMode event_close_mode; + +#if ZM_MEM_MAPPED + int map_fd; + char mem_file[PATH_MAX]; +#else // ZM_MEM_MAPPED + int shm_id; +#endif // ZM_MEM_MAPPED + int mem_size; + unsigned char *mem_ptr; + + SharedData *shared_data; + TriggerData *trigger_data; + + Snapshot *image_buffer; + Snapshot next_buffer; /* Used by four field deinterlacing */ + + Camera *camera; + + Event *event; + + int n_zones; + Zone **zones; + + int iDoNativeMotDet; + + + int n_linked_monitors; + MonitorLink **linked_monitors; + +public: +// OurCheckAlarms seems to be unused. Check it on zm_monitor.cpp for more info. +//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, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, 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_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0, std::string plugins = "", int p_DoNativeMotDect = 1 ); + ~Monitor(); + + void AddZones( int p_n_zones, Zone *p_zones[] ); + + inline int ShmValid() const + { + return( shared_data->valid ); + } + + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } + inline Function GetFunction() const + { + return( function ); + } + inline bool Enabled() + { + if ( function <= MONITOR ) + return( false ); + return( enabled ); + } + inline const char *EventPrefix() const + { + return( event_prefix ); + } + inline bool Ready() + { + if ( function <= MONITOR ) + return( false ); + return( image_count > ready_count ); + } + inline bool Active() + { + if ( function <= MONITOR ) + return( false ); + return( enabled && shared_data->active ); + } + + unsigned int Width() const { return( width ); } + unsigned int Height() const { return( height ); } + unsigned int Colours() const { return( camera->Colours() ); } + unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } + + + State GetState() const; + int GetImage( int index=-1, int scale=100 ) const; + struct timeval GetTimestamp( int index=-1 ) const; + int GetCaptureDelay() const { return( capture_delay ); } + int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } + unsigned int GetLastReadIndex() const; + unsigned int GetLastWriteIndex() const; + unsigned int GetLastEvent() const; + double GetFPS() const; + void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); + void ForceAlarmOff(); + void CancelForced(); + TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); } + + void actionReload(); + void actionEnable(); + void actionDisable(); + void actionSuspend(); + void actionResume(); + + int actionBrightness( int p_brightness=-1 ); + int actionHue( int p_hue=-1 ); + int actionColour( int p_colour=-1 ); + int actionContrast( int p_contrast=-1 ); + + inline int PrimeCapture() + { + return( camera->PrimeCapture() ); + } + inline int PreCapture() + { + return( camera->PreCapture() ); + } + int Capture(); + int PostCapture() + { + return( camera->PostCapture() ); + } + + unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); + // DetectBlack seems to be unused. Check it on zm_monitor.cpp for more info. + //unsigned int DetectBlack( const Image &comp_image, Event::StringSet &zoneSet ); + bool CheckSignal( const Image *image ); + bool Analyse(); + void DumpImage( Image *dump_image ) const; + void TimestampImage( Image *ts_image, const struct timeval *ts_time ) const; + bool closeEvent(); + + void Reload(); + void ReloadZones(); + void ReloadLinkedMonitors( const char * ); + + bool DumpSettings( char *output, bool verbose ); + void DumpZoneImage( const char *zone_string=0 ); + +#if ZM_HAS_V4L + static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ); +#endif // ZM_HAS_V4L + static int LoadRemoteMonitors( const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose ); + static int LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ); +#if HAVE_LIBAVFORMAT + static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); +#endif // HAVE_LIBAVFORMAT + static Monitor *Load( int id, bool load_zones, Purpose purpose ); + //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 StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); + //void StreamImagesZip( int scale=100, int maxfps=10, time_t ttl=0 ); + void SingleImage( int scale=100 ); + void SingleImageRaw( int scale=100 ); + void SingleImageZip( int scale=100 ); +#if HAVE_LIBAVCODEC + //void StreamMpeg( const char *format, int scale=100, int maxfps=10, int bitrate=100000 ); +#endif // HAVE_LIBAVCODEC +}; + +#define MOD_ADD( var, delta, limit ) (((var)+(limit)+(delta))%(limit)) + +class MonitorStream : public StreamBase +{ +protected: + typedef struct SwapImage { + bool valid; + struct timeval timestamp; + char file_name[PATH_MAX]; + } SwapImage; + +private: + SwapImage *temp_image_buffer; + int temp_image_buffer_count; + int temp_read_index; + int temp_write_index; + +protected: + time_t ttl; + +protected: + int playback_buffer; + bool delayed; + + int frame_count; + +protected: + bool checkSwapPath( const char *path, bool create_path ); + + bool sendFrame( const char *filepath, struct timeval *timestamp ); + bool sendFrame( Image *image, struct timeval *timestamp ); + void processCommand( const CmdMsg *msg ); + +public: + MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) + { + } + void setStreamBuffer( int p_playback_buffer ) + { + playback_buffer = p_playback_buffer; + } + void setStreamTTL( time_t p_ttl ) + { + ttl = p_ttl; + } + void setStreamStart( int monitor_id ) + { + loadMonitor( monitor_id ); + } + void runStream(); +}; + +#endif // ZM_MONITOR_H diff --git a/src/zm_monitor.h.orig b/src/zm_monitor.h.orig new file mode 100644 index 000000000..cbc5d75ff --- /dev/null +++ b/src/zm_monitor.h.orig @@ -0,0 +1,458 @@ +// +// ZoneMinder Monitor Class Interfaces, $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. +// + +#ifndef ZM_MONITOR_H +#define ZM_MONITOR_H + +#include "zm.h" +#include "zm_coord.h" +#include "zm_image.h" +#include "zm_rgb.h" +#include "zm_zone.h" +#include "zm_event.h" +#include "zm_camera.h" + +#include +#include + +#define SIGNAL_CAUSE "Signal" +#define MOTION_CAUSE "Motion" +#define LINKED_CAUSE "Linked" + +// +// This is the main class for monitors. Each monitor is associated +// with a camera and is effectively a collector for events. +// +class Monitor +{ +friend class MonitorStream; + +public: + typedef enum + { + QUERY=0, + CAPTURE, + ANALYSIS + } Purpose; + + typedef enum + { + NONE=1, + MONITOR, + MODECT, + RECORD, + MOCORD, + NODECT + } Function; + + typedef enum + { + ROTATE_0=1, + ROTATE_90, + ROTATE_180, + ROTATE_270, + FLIP_HORI, + FLIP_VERT + } Orientation; + + typedef enum + { + IDLE, + PREALARM, + ALARM, + ALERT, + TAPE + } State; + +protected: + typedef std::set ZoneSet; + + typedef enum { GET_SETTINGS=0x1, SET_SETTINGS=0x2, RELOAD=0x4, SUSPEND=0x10, RESUME=0x20 } Action; + + typedef enum { CLOSE_TIME, CLOSE_IDLE, CLOSE_ALARM } EventCloseMode; + + /* sizeof(SharedData) expected to be 336 bytes on 32bit and 64bit */ + typedef struct + { + uint32_t size; /* +0 */ + uint32_t last_write_index; /* +4 */ + uint32_t last_read_index; /* +8 */ + uint32_t state; /* +12 */ + uint32_t last_event; /* +16 */ + uint32_t action; /* +20 */ + int32_t brightness; /* +24 */ + int32_t hue; /* +28 */ + int32_t colour; /* +32 */ + int32_t contrast; /* +36 */ + int32_t alarm_x; /* +40 */ + int32_t alarm_y; /* +44 */ + uint8_t valid; /* +48 */ + uint8_t active; /* +49 */ + uint8_t signal; /* +50 */ + uint8_t format; /* +51 */ + uint32_t imagesize; /* +52 */ + uint32_t epadding1; /* +56 */ + uint32_t epadding2; /* +60 */ + /* + ** This keeps 32bit time_t and 64bit time_t identical and compatible as long as time is before 2038. + ** Shared memory layout should be identical for both 32bit and 64bit and is multiples of 16. + */ + union { /* +64 */ + time_t last_write_time; + uint64_t extrapad1; + }; + union { /* +72 */ + time_t last_read_time; + uint64_t extrapad2; + }; + uint8_t control_state[256]; /* +80 */ + + } SharedData; + + typedef enum { TRIGGER_CANCEL, TRIGGER_ON, TRIGGER_OFF } TriggerState; + + /* sizeof(TriggerData) expected to be 560 on 32bit & and 64bit */ + typedef struct + { + uint32_t size; + uint32_t trigger_state; + uint32_t trigger_score; + uint32_t padding; + char trigger_cause[32]; + char trigger_text[256]; + char trigger_showtext[256]; + } TriggerData; + + /* sizeof(Snapshot) expected to be 16 bytes on 32bit and 32 bytes on 64bit */ + struct Snapshot + { + struct timeval *timestamp; + Image *image; + void* padding; + }; + + class MonitorLink + { + protected: + unsigned int id; + char name[64]; + + bool connected; + time_t last_connect_time; + +#if ZM_MEM_MAPPED + int map_fd; + char mem_file[PATH_MAX]; +#else // ZM_MEM_MAPPED + int shm_id; +#endif // ZM_MEM_MAPPED + int mem_size; + unsigned char *mem_ptr; + + volatile SharedData *shared_data; + volatile TriggerData *trigger_data; + + int last_state; + int last_event; + + public: + MonitorLink( int p_id, const char *p_name ); + ~MonitorLink(); + + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } + + inline bool isConnected() const + { + return( connected ); + } + inline time_t getLastConnectTime() const + { + return( last_connect_time ); + } + + bool connect(); + bool disconnect(); + + bool isAlarmed(); + bool inAlarm(); + bool hasAlarmed(); + }; + +protected: + // These are read from the DB and thereafter remain unchanged + unsigned int id; + char name[64]; + Function function; // What the monitor is doing + 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 height; // Normally the same as the camera, but not if partly rotated + Orientation orientation; // Whether the image has to be rotated at all + unsigned int deinterlacing; + int brightness; // The statically saved brightness of the camera + int contrast; // The statically saved contrast of the camera + int hue; // The statically saved hue of the camera + int colour; // The statically saved colour of the camera + char event_prefix[64]; // The prefix applied to event names as they are created + char label_format[64]; // The format of the timestamp on the images + Coord label_coord; // The coordinates of the timestamp on the images + int image_buffer_count; // Size of circular image buffer, at least twice the size of the pre_event_count + int warmup_count; // How many images to process before looking for events + int pre_event_count; // How many images to hold and prepend to an alarm event + int post_event_count; // How many unalarmed images must occur before the alarm state is reset + int stream_replay_buffer; // How many frames to store to support DVR functions, IGNORED from this object, passed directly into zms now + int section_length; // How long events should last in continuous modes + int frame_skip; // How many frames to skip in continuous modes + int capture_delay; // How long we wait between capture frames + int alarm_capture_delay; // How long we wait between capture frames when in alarm state + int alarm_frame_count; // How many alarm frames are required before an event is triggered + int fps_report_interval; // How many images should be captured/processed between reporting the current FPS + int ref_blend_perc; // Percentage of new image going into reference image. + bool track_motion; // Whether this monitor tries to track detected motion + Rgb signal_check_colour; // The colour that the camera will emit when no video signal detected + + double fps; + Image delta_image; + Image ref_image; + + Purpose purpose; // What this monitor has been created to do + int event_count; + int image_count; + int ready_count; + int first_alarm_count; + int last_alarm_count; + int buffer_count; + int prealarm_count; + State state; + time_t start_time; + time_t last_fps_time; + time_t auto_resume_time; + + EventCloseMode event_close_mode; + +#if ZM_MEM_MAPPED + int map_fd; + char mem_file[PATH_MAX]; +#else // ZM_MEM_MAPPED + int shm_id; +#endif // ZM_MEM_MAPPED + int mem_size; + unsigned char *mem_ptr; + + SharedData *shared_data; + TriggerData *trigger_data; + + Snapshot *image_buffer; + Snapshot next_buffer; /* Used by four field deinterlacing */ + + Camera *camera; + + Event *event; + + int n_zones; + Zone **zones; + + int n_linked_monitors; + MonitorLink **linked_monitors; + +public: + 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, const char *p_event_prefix, const char *p_label_format, const Coord &p_label_coord, 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_capture_delay, int p_alarm_capture_delay, int p_fps_report_interval, int p_ref_blend_perc, bool p_track_motion, Rgb p_signal_check_colour, Purpose p_purpose, int p_n_zones=0, Zone *p_zones[]=0 ); + ~Monitor(); + + void AddZones( int p_n_zones, Zone *p_zones[] ); + + inline int ShmValid() const + { + return( shared_data->valid ); + } + + inline int Id() const + { + return( id ); + } + inline const char *Name() const + { + return( name ); + } + inline Function GetFunction() const + { + return( function ); + } + inline bool Enabled() + { + if ( function <= MONITOR ) + return( false ); + return( enabled ); + } + inline const char *EventPrefix() const + { + return( event_prefix ); + } + inline bool Ready() + { + if ( function <= MONITOR ) + return( false ); + return( image_count > ready_count ); + } + inline bool Active() + { + if ( function <= MONITOR ) + return( false ); + return( enabled && shared_data->active ); + } + + unsigned int Width() const { return( width ); } + unsigned int Height() const { return( height ); } + unsigned int Colours() const { return( camera->Colours() ); } + unsigned int SubpixelOrder() const { return( camera->SubpixelOrder() ); } + + + State GetState() const; + int GetImage( int index=-1, int scale=100 ) const; + struct timeval GetTimestamp( int index=-1 ) const; + int GetCaptureDelay() const { return( capture_delay ); } + int GetAlarmCaptureDelay() const { return( alarm_capture_delay ); } + unsigned int GetLastReadIndex() const; + unsigned int GetLastWriteIndex() const; + unsigned int GetLastEvent() const; + double GetFPS() const; + void ForceAlarmOn( int force_score, const char *force_case, const char *force_text="" ); + void ForceAlarmOff(); + void CancelForced(); + TriggerState GetTriggerState() const { return( (TriggerState)(trigger_data?trigger_data->trigger_state:TRIGGER_CANCEL )); } + + void actionReload(); + void actionEnable(); + void actionDisable(); + void actionSuspend(); + void actionResume(); + + int actionBrightness( int p_brightness=-1 ); + int actionHue( int p_hue=-1 ); + int actionColour( int p_colour=-1 ); + int actionContrast( int p_contrast=-1 ); + + inline int PrimeCapture() + { + return( camera->PrimeCapture() ); + } + inline int PreCapture() + { + return( camera->PreCapture() ); + } + int Capture(); + int PostCapture() + { + return( camera->PostCapture() ); + } + + unsigned int DetectMotion( const Image &comp_image, Event::StringSet &zoneSet ); + bool CheckSignal( const Image *image ); + bool Analyse(); + void DumpImage( Image *dump_image ) const; + void TimestampImage( Image *ts_image, const struct timeval *ts_time ) const; + bool closeEvent(); + + void Reload(); + void ReloadZones(); + void ReloadLinkedMonitors( const char * ); + + bool DumpSettings( char *output, bool verbose ); + void DumpZoneImage( const char *zone_string=0 ); + +#if ZM_HAS_V4L + static int LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose purpose ); +#endif // ZM_HAS_V4L + static int LoadRemoteMonitors( const char *protocol, const char *host, const char*port, const char*path, Monitor **&monitors, Purpose purpose ); + static int LoadFileMonitors( const char *file, Monitor **&monitors, Purpose purpose ); +#if HAVE_LIBAVFORMAT + static int LoadFfmpegMonitors( const char *file, Monitor **&monitors, Purpose purpose ); +#endif // HAVE_LIBAVFORMAT + static Monitor *Load( int id, bool load_zones, Purpose purpose ); + //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 StreamImagesRaw( int scale=100, int maxfps=10, time_t ttl=0 ); + //void StreamImagesZip( int scale=100, int maxfps=10, time_t ttl=0 ); + void SingleImage( int scale=100 ); + void SingleImageRaw( int scale=100 ); + void SingleImageZip( int scale=100 ); +#if HAVE_LIBAVCODEC + //void StreamMpeg( const char *format, int scale=100, int maxfps=10, int bitrate=100000 ); +#endif // HAVE_LIBAVCODEC +}; + +#define MOD_ADD( var, delta, limit ) (((var)+(limit)+(delta))%(limit)) + +class MonitorStream : public StreamBase +{ +protected: + typedef struct SwapImage { + bool valid; + struct timeval timestamp; + char file_name[PATH_MAX]; + } SwapImage; + +private: + SwapImage *temp_image_buffer; + int temp_image_buffer_count; + int temp_read_index; + int temp_write_index; + +protected: + time_t ttl; + +protected: + int playback_buffer; + bool delayed; + + int frame_count; + +protected: + bool checkSwapPath( const char *path, bool create_path ); + + bool sendFrame( const char *filepath, struct timeval *timestamp ); + bool sendFrame( Image *image, struct timeval *timestamp ); + void processCommand( const CmdMsg *msg ); + +public: + MonitorStream() : playback_buffer( 0 ), delayed( false ), frame_count( 0 ) + { + } + void setStreamBuffer( int p_playback_buffer ) + { + playback_buffer = p_playback_buffer; + } + void setStreamTTL( time_t p_ttl ) + { + ttl = p_ttl; + } + void setStreamStart( int monitor_id ) + { + loadMonitor( monitor_id ); + } + void runStream(); +}; + +#endif // ZM_MONITOR_H diff --git a/src/zm_mpeg.cpp b/src/zm_mpeg.cpp new file mode 100644 index 000000000..3c453ba39 --- /dev/null +++ b/src/zm_mpeg.cpp @@ -0,0 +1,486 @@ +/* + * ZoneMinder MPEG class implementation, $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. +*/ + +#include +#include + +#include "zm.h" +#include "zm_rgb.h" +#include "zm_mpeg.h" + +#if HAVE_LIBAVCODEC + + +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(54, 1, 0) +static int encode_frame(AVCodecContext *c, AVFrame *frame) +{ + AVPacket pkt = { 0 }; + int ret, got_output; + + av_init_packet(&pkt); + av_init_packet(&pkt); + ret = avcodec_encode_video2(c, &pkt, frame, &got_output); + if (ret < 0) + return ret; + + ret = pkt.size; + av_free_packet(&pkt); + return ret; +} +#endif + +bool VideoStream::initialised = false; + +VideoStream::MimeData VideoStream::mime_data[] = { + { "asf", "video/x-ms-asf" }, + { "swf", "application/x-shockwave-flash" }, + { "flv", "video/x-flv" }, + { "mp4", "video/mp4" }, + { "move", "video/quicktime" } +}; + +void VideoStream::Initialise() +{ + av_register_all(); + initialised = true; +} + +void VideoStream::SetupFormat( const char *p_filename, const char *p_format ) +{ + filename = p_filename; + format = p_format; + + /* auto detect the output format from the name. default is mpeg. */ + of = av_guess_format( format, NULL, NULL); + if ( !of ) + { + Warning( "Could not deduce output format from file extension: using mpeg" ); + of = av_guess_format("mpeg", NULL, NULL); + } + if ( !of ) + { + Fatal( "Could not find suitable output format" ); + } + + /* allocate the output media context */ + ofc = (AVFormatContext *)av_mallocz(sizeof(AVFormatContext)); + if ( !ofc ) + { + Panic( "Memory error" ); + } + ofc->oformat = of; + snprintf( ofc->filename, sizeof(ofc->filename), "%s", filename ); +} + +void VideoStream::SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ) +{ + /* ffmpeg format matching */ + switch(colours) { + case ZM_COLOUR_RGB24: + { + if(subpixelorder == ZM_SUBPIX_ORDER_BGR) { + /* BGR subpixel order */ + pf = PIX_FMT_BGR24; + } else { + /* Assume RGB subpixel order */ + pf = PIX_FMT_RGB24; + } + break; + } + case ZM_COLOUR_RGB32: + { + if(subpixelorder == ZM_SUBPIX_ORDER_ARGB) { + /* ARGB subpixel order */ + pf = PIX_FMT_ARGB; + } else if(subpixelorder == ZM_SUBPIX_ORDER_ABGR) { + /* ABGR subpixel order */ + pf = PIX_FMT_ABGR; + } else if(subpixelorder == ZM_SUBPIX_ORDER_BGRA) { + /* BGRA subpixel order */ + pf = PIX_FMT_BGRA; + } else { + /* Assume RGBA subpixel order */ + pf = PIX_FMT_RGBA; + } + break; + } + case ZM_COLOUR_GRAY8: + pf = PIX_FMT_GRAY8; + break; + default: + Panic("Unexpected colours: %d",colours); + break; + } + + /* add the video streams using the default format codecs + and initialize the codecs */ + ost = NULL; + if (of->video_codec != CODEC_ID_NONE) + { +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + ost = av_new_stream(ofc, 0); +#else + ost = avformat_new_stream(ofc, 0); +#endif + if (!ost) + { + Panic( "Could not alloc stream" ); + } + +#if ZM_FFMPEG_SVN + AVCodecContext *c = ost->codec; +#else + AVCodecContext *c = &ost->codec; +#endif + + c->codec_id = of->video_codec; +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + c->codec_type = AVMEDIA_TYPE_VIDEO; +#else + c->codec_type = CODEC_TYPE_VIDEO; +#endif + + /* put sample parameters */ + c->bit_rate = bitrate; + c->pix_fmt = PIX_FMT_YUV420P; + /* resolution must be a multiple of two */ + c->width = width; + c->height = height; +#if ZM_FFMPEG_SVN + /* time base: this is the fundamental unit of time (in seconds) in terms + of which frame timestamps are represented. for fixed-fps content, + timebase should be 1/framerate and timestamp increments should be + identically 1. */ + //c->time_base.den = (int)(frame_rate*100); + //c->time_base.num = 100; + c->time_base.den = frame_rate; + c->time_base.num = 1; +#else + /* frames per second */ + c->frame_rate = frame_rate; + c->frame_rate_base = 1; +#endif + //c->gop_size = frame_rate/2; /* emit one intra frame every half second or so */ + c->gop_size = 12; + if ( c->gop_size < 3 ) + c->gop_size = 3; + // some formats want stream headers to be seperate + if(!strcmp(ofc->oformat->name, "mp4") || !strcmp(ofc->oformat->name, "mov") || !strcmp(ofc->oformat->name, "3gp")) + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + } +} + +void VideoStream::SetParameters() +{ + /* set the output parameters (must be done even if no + parameters). */ +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + if ( av_set_parameters(ofc, NULL) < 0 ) +#else + if ( avformat_write_header(ofc, NULL) < 0 ) +#endif + { + Panic( "Invalid output format parameters" ); + } + //dump_format(ofc, 0, filename, 1); +} + +const char *VideoStream::MimeType() const +{ + for ( unsigned int i = 0; i < sizeof(mime_data)/sizeof(*mime_data); i++ ) + { + if ( strcmp( format, mime_data[i].format ) == 0 ) + { + return( mime_data[i].mime_type ); + } + } + const char *mime_type = of->mime_type; + if ( !mime_type ) + { + mime_type = "video/mpeg"; + Warning( "Unable to determine mime type for '%s' format, using '%s' as default", format, mime_type ); + } + + return( mime_type ); +} + +void VideoStream::OpenStream() +{ + /* now that all the parameters are set, we can open the + video codecs and allocate the necessary encode buffers */ + if ( ost ) + { +#if ZM_FFMPEG_SVN + AVCodecContext *c = ost->codec; +#else + AVCodecContext *c = &ost->codec; +#endif + + /* find the video encoder */ + AVCodec *codec = avcodec_find_encoder(c->codec_id); + if ( !codec ) + { + Panic( "codec not found" ); + } + + /* open the codec */ +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0) + if ( avcodec_open(c, codec) < 0 ) +#else + if ( avcodec_open2(c, codec, 0) < 0 ) +#endif + { + Panic( "Could not open codec" ); + } + + /* allocate the encoded raw picture */ + opicture = avcodec_alloc_frame(); + if ( !opicture ) + { + Panic( "Could not allocate opicture" ); + } + int size = avpicture_get_size( c->pix_fmt, c->width, c->height); + uint8_t *opicture_buf = (uint8_t *)av_malloc(size); + if ( !opicture_buf ) + { + av_free(opicture); + Panic( "Could not allocate opicture" ); + } + avpicture_fill( (AVPicture *)opicture, opicture_buf, c->pix_fmt, c->width, c->height ); + + /* if the output format is not identical to the input format, then a temporary + picture is needed too. It is then converted to the required + output format */ + tmp_opicture = NULL; + if ( c->pix_fmt != pf ) + { + tmp_opicture = avcodec_alloc_frame(); + if ( !tmp_opicture ) + { + Panic( "Could not allocate temporary opicture" ); + } + int size = avpicture_get_size( pf, c->width, c->height); + uint8_t *tmp_opicture_buf = (uint8_t *)av_malloc(size); + if (!tmp_opicture_buf) + { + av_free( tmp_opicture ); + Panic( "Could not allocate temporary opicture" ); + } + avpicture_fill( (AVPicture *)tmp_opicture, tmp_opicture_buf, pf, c->width, c->height ); + } + } + + /* open the output file, if needed */ + if ( !(of->flags & AVFMT_NOFILE) ) + { +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + if ( avio_open(&ofc->pb, filename, AVIO_FLAG_WRITE) < 0 ) +#else + if ( url_fopen(&ofc->pb, filename, AVIO_FLAG_WRITE) < 0 ) +#endif + { + Fatal( "Could not open '%s'", filename ); + } + } + + video_outbuf = NULL; + if ( !(ofc->oformat->flags & AVFMT_RAWPICTURE) ) + { + /* allocate output buffer */ + /* XXX: API change will be done */ + video_outbuf_size = 200000; + video_outbuf = (uint8_t *)malloc(video_outbuf_size); + } + + /* write the stream header, if any */ +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 4, 0) + av_write_header(ofc); +#else + avformat_write_header(ofc, NULL); +#endif +} + +VideoStream::VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ) +{ + if ( !initialised ) + { + Initialise(); + } + + SetupFormat( filename, format ); + SetupCodec( colours, subpixelorder, width, height, bitrate, frame_rate ); + SetParameters(); +} + +VideoStream::~VideoStream() +{ + /* close each codec */ + if (ost) + { +#if ZM_FFMPEG_SVN + avcodec_close(ost->codec); +#else + avcodec_close(&ost->codec); +#endif + av_free(opicture->data[0]); + av_free(opicture); + if (tmp_opicture) + { + av_free(tmp_opicture->data[0]); + av_free(tmp_opicture); + } + av_free(video_outbuf); + } + + /* write the trailer, if any */ + av_write_trailer(ofc); + + /* free the streams */ + for( unsigned int i = 0; i < ofc->nb_streams; i++) + { + av_freep(&ofc->streams[i]); + } + + if (!(of->flags & AVFMT_NOFILE)) + { + /* close the output file */ +#if ZM_FFMPEG_SVN +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + avio_close(ofc->pb); +#else + url_fclose(ofc->pb); +#endif +#else + url_fclose(&ofc->pb); +#endif + } + + /* free the stream */ + av_free(ofc); +} + +double VideoStream::EncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp, unsigned int timestamp ) +{ +#ifdef HAVE_LIBSWSCALE + static struct SwsContext *img_convert_ctx = 0; +#endif // HAVE_LIBSWSCALE + double pts = 0.0; + + + if (ost) + { +#if ZM_FFMPEG_048 + pts = (double)ost->pts.val * ofc->pts_num / ofc->pts_den; +#else + pts = (double)ost->pts.val * ost->time_base.num / ost->time_base.den; +#endif + } + +#if ZM_FFMPEG_SVN + AVCodecContext *c = ost->codec; +#else + AVCodecContext *c = &ost->codec; +#endif + if ( c->pix_fmt != pf ) + { + memcpy( tmp_opicture->data[0], buffer, buffer_size ); +#ifdef HAVE_LIBSWSCALE + if ( !img_convert_ctx ) + { + img_convert_ctx = sws_getCachedContext( NULL, c->width, c->height, pf, c->width, c->height, c->pix_fmt, SWS_BICUBIC, NULL, NULL, NULL ); + if ( !img_convert_ctx ) + Panic( "Unable to initialise image scaling context" ); + } + sws_scale( img_convert_ctx, tmp_opicture->data, tmp_opicture->linesize, 0, c->height, opicture->data, opicture->linesize ); +#else // HAVE_LIBSWSCALE + Fatal("swscale is required for MPEG mode"); +#endif // HAVE_LIBSWSCALE + } + else + { + memcpy( opicture->data[0], buffer, buffer_size ); + } + AVFrame *opicture_ptr = opicture; + + int ret = 0; + if ( ofc->oformat->flags & AVFMT_RAWPICTURE ) + { +#if ZM_FFMPEG_048 + ret = av_write_frame( ofc, ost->index, (uint8_t *)opicture_ptr, sizeof(AVPicture) ); +#else + AVPacket pkt; + av_init_packet( &pkt ); + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + pkt.flags |= AV_PKT_FLAG_KEY; +#else + pkt.flags |= PKT_FLAG_KEY; +#endif + pkt.stream_index = ost->index; + pkt.data = (uint8_t *)opicture_ptr; + pkt.size = sizeof(AVPicture); + + ret = av_write_frame(ofc, &pkt); +#endif + } + else + { + if ( add_timestamp ) + ost->pts.val = timestamp; +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(54, 1, 0) // NEXTIME + int out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, opicture_ptr); +#else + int out_size = encode_frame(c, opicture_ptr); + +#endif + if ( out_size > 0 ) + { +#if ZM_FFMPEG_048 + ret = av_write_frame(ofc, ost->index, video_outbuf, out_size); +#else + AVPacket pkt; + av_init_packet(&pkt); + +#if ZM_FFMPEG_049 + pkt.pts = c->coded_frame->pts; +#else + pkt.pts= av_rescale_q( c->coded_frame->pts, c->time_base, ost->time_base ); +#endif + if(c->coded_frame->key_frame) +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + pkt.flags |= AV_PKT_FLAG_KEY; +#else + pkt.flags |= PKT_FLAG_KEY; +#endif + pkt.stream_index = ost->index; + pkt.data = video_outbuf; + pkt.size = out_size; + + ret = av_write_frame( ofc, &pkt ); +#endif + } + } + if ( ret != 0 ) + { + Fatal( "Error %d while writing video frame: %s", ret, strerror( errno ) ); + } + return( pts ); +} + +#endif // HAVE_LIBAVCODEC diff --git a/src/zm_mpeg.h b/src/zm_mpeg.h new file mode 100644 index 000000000..c7cb4d26f --- /dev/null +++ b/src/zm_mpeg.h @@ -0,0 +1,70 @@ +/* + * ZoneMinder MPEG Interface, $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. +*/ + +#ifndef ZM_MPEG_H +#define ZM_MPEG_H + +#include "zm_ffmpeg.h" + +#if HAVE_LIBAVCODEC + +class VideoStream +{ +protected: + struct MimeData + { + const char *format; + const char *mime_type; + }; + +protected: + static bool initialised; + static struct MimeData mime_data[]; + +protected: + const char *filename; + const char *format; + enum PixelFormat pf; + AVOutputFormat *of; + AVFormatContext *ofc; + AVStream *ost; + AVFrame *opicture; + AVFrame *tmp_opicture; + uint8_t *video_outbuf; + int video_outbuf_size; + double pts; + +protected: + static void Initialise(); + + void SetupFormat( const char *p_filename, const char *format ); + void SetupCodec( int colours, int subpixelorder, int width, int height, int bitrate, double frame_rate ); + void SetParameters(); + +public: + VideoStream( const char *filename, const char *format, int bitrate, double frame_rate, int colours, int subpixelorder, int width, int height ); + ~VideoStream(); + const char *MimeType() const; + void OpenStream(); + double EncodeFrame( const uint8_t *buffer, int buffer_size, bool add_timestamp=false, unsigned int timestamp=0 ); +}; + +#endif // HAVE_LIBAVCODEC + +#endif // ZM_MPEG_H diff --git a/src/zm_plugin.cpp b/src/zm_plugin.cpp new file mode 100644 index 000000000..29a068135 --- /dev/null +++ b/src/zm_plugin.cpp @@ -0,0 +1,105 @@ +#include "zm_plugin.h" + + + +/*!\fn Plugin::Plugin(const std::string &sFilename) + * \param sFilename is the name of plugin file to load + */ +Plugin::Plugin(const std::string &sFilename) + : m_sPluginFileName(sFilename), + m_hDLL(0), + m_pDLLRefCount(0), + m_pfnGetEngineVersion(0), + m_pfnRegisterPlugin(0) +{ + + // Try to load the plugin as a dynamic library + m_hDLL = dlopen(sFilename.c_str(), RTLD_LAZY|RTLD_GLOBAL); + + if(!m_hDLL) // if library hasn't been loaded successfully + { + throw runtime_error(string("Could not load '") + sFilename + "'"); + } + + // Locate the plugin's exported functions + try + { + m_pfnGetEngineVersion = reinterpret_cast(dlsym(m_hDLL, "getEngineVersion")); + m_pfnRegisterPlugin = reinterpret_cast(dlsym(m_hDLL, "registerPlugin")); + + // If the functions aren't found, we're going to assume this is + // a plain simple DLL and not one of our plugins + if(!m_pfnGetEngineVersion || ! m_pfnRegisterPlugin) + throw runtime_error(string("'") + sFilename + "' is not a valid plugin"); + + // Initialize a new DLL reference counter + m_pDLLRefCount = new size_t(1); + } + catch(runtime_error &ex) + { + dlclose(m_hDLL); + throw ex; + } + catch(...) + { + dlclose(m_hDLL); + throw runtime_error(string("Unknown exception while loading plugin '") + sFilename + string("'")); + } +} + + + +/*!\fn Plugin::Plugin(const Plugin &Other) + * \param Other is the other plugin instance to copy + */ +Plugin::Plugin(const Plugin &Other) + : m_sPluginFileName(Other.m_sPluginFileName), + m_hDLL(Other.m_hDLL), + m_pDLLRefCount(Other.m_pDLLRefCount), + m_pfnGetEngineVersion(Other.m_pfnGetEngineVersion), + m_pfnRegisterPlugin(Other.m_pfnRegisterPlugin) +{ + // Increase DLL reference counter + ++*m_pDLLRefCount; +} + + + +/*!\fn Plugin::operator=(const Plugin &Other) + * \param Other is the other plugin instance to copy + * return copy of object + */ +Plugin& Plugin::operator=(const Plugin &Other) +{ + m_hDLL = Other.m_hDLL; + m_pfnGetEngineVersion = Other.m_pfnGetEngineVersion; + m_pfnRegisterPlugin = Other.m_pfnRegisterPlugin; + m_pDLLRefCount = Other.m_pDLLRefCount; + m_sPluginFileName = Other.m_sPluginFileName; + // Increase DLL reference counter + ++*m_pDLLRefCount; + return *this; + +} + + + +Plugin::~Plugin() +{ + // Only unload the DLL if there are no more references to it + if(!--*m_pDLLRefCount) + { + delete m_pDLLRefCount; + dlclose(m_hDLL); + } +} + + + +/*!\fn Plugin::registerPlugin(PluginManager &K) + * \param K is the pointer to plugin manager + */ +void Plugin::registerPlugin(PluginManager &K) +{ + m_pfnRegisterPlugin(K, m_sPluginFileName); +} diff --git a/src/zm_plugin.h b/src/zm_plugin.h new file mode 100644 index 000000000..a9247d646 --- /dev/null +++ b/src/zm_plugin.h @@ -0,0 +1,78 @@ +#ifndef ZM_PLUGIN_H +#define ZM_PLUGIN_H + + + +#include +#include +#include + +#include +#include "zm.h" + + + +using namespace std; + + + +class PluginManager; + + + +//! Signature for the version query function +typedef int fnGetEngineVersion(); + +//! Signature for the plugin's registration function +typedef void fnRegisterPlugin(PluginManager &, string); + + + +//! Representation of a plugin. +/*! Use for loading plugin's shared library + * and registration of it to the PluginManager. + */ +class Plugin +{ + +public: + + //! Initialize and load plugin + Plugin(const std::string &sFilename); + + //! Copy existing plugin instance + Plugin(const Plugin &Other); + + //! Operator =. + Plugin &operator =(const Plugin &Other); + + //! Unload a plugin + ~Plugin(); + + //! Query the plugin for its expected engine version + int getEngineVersion() const { return m_pfnGetEngineVersion();} + + //! Register the plugin to a PluginManager + void registerPlugin(PluginManager &K); + +private: + + //! Shared file name. + string m_sPluginFileName; + + //! DLL handle + void* m_hDLL; + + //! Number of references to the DLL + size_t *m_pDLLRefCount; + + //! Version query function + fnGetEngineVersion *m_pfnGetEngineVersion; + + //! Plugin registration function + fnRegisterPlugin *m_pfnRegisterPlugin; +}; + + + +#endif //ZM_PLUGIN_H diff --git a/src/zm_plugin_manager.cpp b/src/zm_plugin_manager.cpp new file mode 100644 index 000000000..5b9701957 --- /dev/null +++ b/src/zm_plugin_manager.cpp @@ -0,0 +1,118 @@ +#include "zm_plugin_manager.h" + + + +/*! \fn file_select(const struct direct *entry) + * A functor for selection of files with specified extension. + * \param entry is file structure + * \return 1 if file match selection criteria and + * 0 otherwise. + * NOTE: file extension is specified by PluginManager::m_sPluginExt + * static variable. + */ +int file_select(const struct direct *entry) +{ + char *ptr; + + if ((strcmp(entry->d_name, ".")== 0) || (strcmp(entry->d_name, "..") == 0)) + return 0; + + // Check for filename extensions. + ptr = rindex((char*)entry->d_name, '.'); + if ((ptr != NULL) && (strcmp(ptr, (PluginManager::m_sPluginExt).c_str()) == 0)) + return 1; + else + return 0; +} + + + + +/*! \fn join_paths(const string& p1, const string& p2) + * \param p1 is the first part of desired path + * \param p2 is the second part of desired path + * \return joined path string. + */ +string join_paths(const string& p1, const string& p2) +{ + char sep = '/'; + string tmp = p1; + +#ifdef _WIN32 + sep = '\\'; +#endif + + if (p1[p1.length()] != sep) + { // Need to add a path separator + tmp += sep; + return(tmp + p2); + } + else + return(p1 + p2); +} + + + +string PluginManager::m_sPluginExt = DEFAULT_PLUGIN_EXT; + + +PluginManager::PluginManager() +{ +} + + + +/*!\fn PluginManager::loadPlugin(const string &sFilename)) + * \param sFilename is the name of plugin file to load + */ +void PluginManager::loadPlugin(const string &sFilename) +{ + try + { + if(m_LoadedPlugins.find(sFilename) == m_LoadedPlugins.end()) + m_LoadedPlugins.insert(PluginMap::value_type(sFilename, Plugin(sFilename))).first->second.registerPlugin(*this); + } + catch(runtime_error &ex) + { + Info("Runtime error: %s", ex.what()); + } + catch(...) + { + Info("Unknown exception. Could not load %s.", sFilename.c_str()); + } +} + + + +/*!\fn PluginManager::findPlugins(const string &sPath) + * \param sPath is the path to folder to search plugins + * return count of found plugins + */ +int PluginManager::findPlugins(const string &sPath) +{ + + struct direct **files; + + int count = scandir(sPath.c_str(), &files, file_select, alphasort); + + for (int i = 1; i < count + 1; ++i) + { + string sFileName = files[i-1]->d_name; + string sFullPath = join_paths(sPath, sFileName); + + Info("Loading plugin %s ... ", sFullPath.c_str()); + + loadPlugin(sFullPath); + } + + return count; +} + + +/*!\fn PluginManager::configurePlugins(string sConfigFileName) + * \param sConfigFileName is the path to the configuration file, where parameters for all plugins are given. + */ +void PluginManager::configurePlugins(string sConfigFileName) +{ + m_ImageAnalyser.configurePlugins(sConfigFileName); +} diff --git a/src/zm_plugin_manager.h b/src/zm_plugin_manager.h new file mode 100644 index 000000000..b108dd74a --- /dev/null +++ b/src/zm_plugin_manager.h @@ -0,0 +1,85 @@ +#ifndef ZM_PLUGIN_MANAGER_H +#define ZM_PLUGIN_MANAGER_H + + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_image_analyser.h" +#include "zm_detector.h" +#include "zm_plugin.h" + + + +using namespace std; + + +#define ZM_ENGINE_VERSION 24 +#define DEFAULT_PLUGIN_EXT ".zmpl" + + + +//! Map of plugins by their associated file names. +typedef std::map PluginMap; + + +//! External function for sorting of files in directory. +extern int alphasort(); + + +//! Function to select files with plugins by extension. +int file_select(const struct direct *entry); + + +//! Join two path strings. +string join_paths(const string& p1, const string& p2); + + + +//! Class for managing all loaded plugins. +class PluginManager +{ + +public: + + //! Default constructor. + PluginManager(); + + //! Access the image analyser. + ImageAnalyser &getImageAnalyser() {return m_ImageAnalyser;} + + //! Loads a plugin. + void loadPlugin(const string &sFilename); + + //! Find and load all plugins from given directory, returns number of found plugins. + int findPlugins(const string &sPath); + + //! Configure all loaded plugins using given configuration file. + void configurePlugins(string sConfigFileName); + + //! Set plugin extension. + void setPluginExt(string sPluginExt) { m_sPluginExt = sPluginExt; } + + //! Extension for zm plugins. + static string m_sPluginExt; + +private: + + //! All plugins currently loaded. + PluginMap m_LoadedPlugins; + + //! The image analyser. + ImageAnalyser m_ImageAnalyser; +}; + + + +#endif //ZM_PLUGIN_MANAGER_H diff --git a/src/zm_poly.cpp b/src/zm_poly.cpp new file mode 100644 index 000000000..eef5dd56a --- /dev/null +++ b/src/zm_poly.cpp @@ -0,0 +1,118 @@ +// +// ZoneMinder Polygon Class Implementation, $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. +// + +#include "zm.h" +#include "zm_poly.h" + +#include + +void Polygon::calcArea() +{ + double float_area = 0.0L; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + double trap_area = ((coords[i].X()-coords[j].X())*((coords[i].Y()+coords[j].Y())))/2.0L; + float_area += trap_area; + //printf( "%.2f (%.2f)\n", float_area, trap_area ); + } + area = (int)round(fabs(float_area)); +} + +void Polygon::calcCentre() +{ + if ( !area && n_coords ) + calcArea(); + double float_x = 0.0L, float_y = 0.0L; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + float_x += ((coords[i].Y()-coords[j].Y())*((coords[i].X()*2)+(coords[i].X()*coords[j].X())+(coords[j].X()*2))); + float_y += ((coords[j].X()-coords[i].X())*((coords[i].Y()*2)+(coords[i].Y()*coords[j].Y())+(coords[j].Y()*2))); + } + float_x /= (6*area); + float_y /= (6*area); + //printf( "%.2f,%.2f\n", float_x, float_y ); + centre = Coord( (int)round(float_x), (int)round(float_y) ); +} + +Polygon::Polygon( int p_n_coords, const Coord *p_coords ) : n_coords( p_n_coords ) +{ + coords = new Coord[n_coords]; + + int min_x = -1; + int max_x = -1; + int min_y = -1; + int max_y = -1; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_coords[i]; + if ( min_x == -1 || coords[i].X() < min_x ) + min_x = coords[i].X(); + if ( max_x == -1 || coords[i].X() > max_x ) + max_x = coords[i].X(); + if ( min_y == -1 || coords[i].Y() < min_y ) + min_y = coords[i].Y(); + if ( max_y == -1 || coords[i].Y() > max_y ) + max_y = coords[i].Y(); + } + extent = Box( min_x, min_y, max_x, max_y ); + calcArea(); + calcCentre(); +} + +Polygon::Polygon( const Polygon &p_polygon ) : n_coords( p_polygon.n_coords ), extent( p_polygon.extent ), area( p_polygon.area ), centre( p_polygon.centre ) +{ + coords = new Coord[n_coords]; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_polygon.coords[i]; + } +} + +Polygon &Polygon::operator=( const Polygon &p_polygon ) +{ + if ( n_coords < p_polygon.n_coords ) + { + delete[] coords; + coords = new Coord[p_polygon.n_coords]; + } + n_coords = p_polygon.n_coords; + for( int i = 0; i < n_coords; i++ ) + { + coords[i] = p_polygon.coords[i]; + } + extent = p_polygon.extent; + area = p_polygon.area; + centre = p_polygon.centre; + return( *this ); +} + +bool Polygon::isInside( const Coord &coord ) const +{ + bool inside = false; + for ( int i = 0, j = n_coords-1; i < n_coords; j = i++ ) + { + if ( (((coords[i].Y() <= coord.Y()) && (coord.Y() < coords[j].Y()) ) + || ((coords[j].Y() <= coord.Y()) && (coord.Y() < coords[i].Y()))) + && (coord.X() < (coords[j].X() - coords[i].X()) * (coord.Y() - coords[i].Y()) / (coords[j].Y() - coords[i].Y()) + coords[i].X())) + { + inside = !inside; + } + } + return( inside ); +} diff --git a/src/zm_poly.h b/src/zm_poly.h new file mode 100644 index 000000000..854a3c322 --- /dev/null +++ b/src/zm_poly.h @@ -0,0 +1,125 @@ +// +// ZoneMinder Polygon Class Interfaces, $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. +// + +#ifndef ZM_POLY_H +#define ZM_POLY_H + +#include "zm.h" +#include "zm_coord.h" +#include "zm_box.h" + +#include + +// +// Class used for storing a box, which is defined as a region +// defined by two coordinates +// +class Polygon +{ +protected: + struct Edge + { + int min_y; + int max_y; + double min_x; + double _1_m; + + static int CompareYX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + if ( e1->min_y == e2->min_y ) + return( int(e1->min_x - e2->min_x) ); + else + return( int(e1->min_y - e2->min_y) ); + } + static int CompareX( const void *p1, const void *p2 ) + { + const Edge *e1 = (const Edge *)p1, *e2 = (const Edge *)p2; + return( int(e1->min_x - e2->min_x) ); + } + }; + + struct Slice + { + int min_x; + int max_x; + int n_edges; + int *edges; + + Slice() + { + n_edges = 0; + edges = 0; + } + ~Slice() + { + delete edges; + } + }; + +protected: + int n_coords; + Coord *coords; + Box extent; + int area; + Coord centre; + Edge *edges; + Slice *slices; + +protected: + void initialiseEdges(); + void calcArea(); + void calcCentre(); + +public: + inline Polygon() : n_coords( 0 ), coords( 0 ), area( 0 ) + { + } + Polygon( int p_n_coords, const Coord *p_coords ); + Polygon( const Polygon &p_polygon ); + ~Polygon() + { + delete[] coords; + } + + Polygon &operator=( const Polygon &p_polygon ); + + inline int getNumCoords() const { return( n_coords ); } + inline const Coord &getCoord( int index ) const + { + return( coords[index] ); + } + + inline const Box &Extent() const { return( extent ); } + inline int LoX() const { return( extent.LoX() ); } + inline int HiX() const { return( extent.HiX() ); } + inline int LoY() const { return( extent.LoY() ); } + inline int HiY() const { return( extent.HiY() ); } + inline int Width() const { return( extent.Width() ); } + inline int Height() const { return( extent.Height() ); } + + inline int Area() const { return( area ); } + inline const Coord &Centre() const + { + return( centre ); + } + bool isInside( const Coord &coord ) const; +}; + +#endif // ZM_POLY_H diff --git a/src/zm_regexp.cpp b/src/zm_regexp.cpp new file mode 100644 index 000000000..43f738217 --- /dev/null +++ b/src/zm_regexp.cpp @@ -0,0 +1,124 @@ +/* + * ZoneMinder regular expression class implementation, $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. +*/ + +#include + +#include "zm.h" +#include "zm_regexp.h" + +#if HAVE_LIBPCRE + +RegExpr::RegExpr( const char *pattern, int flags, int p_max_matches ) : max_matches( p_max_matches ), match_buffers( 0 ), match_lengths( 0 ), match_valid( 0 ) +{ + const char *errstr; + int erroffset = 0; + if ( !(regex = pcre_compile( pattern, flags, &errstr, &erroffset, 0 )) ) + { + Panic( "pcre_compile(%s): %s at %d", pattern, errstr, erroffset ); + } + + regextra = pcre_study( regex, 0, &errstr ); + if ( errstr ) + { + Panic( "pcre_study(%s): %s", pattern, errstr ); + } + + if ( (ok = (bool)regex) ) + { + match_vectors = new int[3*max_matches]; + memset( match_vectors, 0, sizeof(*match_vectors)*3*max_matches ); + match_buffers = new char *[max_matches]; + memset( match_buffers, 0, sizeof(*match_buffers)*max_matches ); + match_lengths = new int[max_matches]; + memset( match_lengths, 0, sizeof(*match_lengths)*max_matches ); + match_valid = new bool[max_matches]; + memset( match_valid, 0, sizeof(*match_valid)*max_matches ); + } + n_matches = 0; +} + +RegExpr::~RegExpr() +{ + for ( int i = 0; i < max_matches; i++ ) + { + if ( match_buffers[i] ) + { + delete[] match_buffers[i]; + } + } + delete[] match_valid; + delete[] match_lengths; + delete[] match_buffers; + delete[] match_vectors; +} + +int RegExpr::Match( const char *subject_string, int subject_length, int flags ) +{ + match_string = subject_string; + + n_matches = pcre_exec( regex, regextra, subject_string, subject_length, 0, flags, match_vectors, 2*max_matches ); + + if ( n_matches <= 0 ) + { + if ( n_matches < PCRE_ERROR_NOMATCH ) + { + Error( "Error %d executing regular expression", n_matches ); + } + return( n_matches = 0 ); + } + + for( int i = 0; i < max_matches; i++ ) + { + match_valid[i] = false; + } + return( n_matches ); +} + +const char *RegExpr::MatchString( int match_index ) const +{ + if ( match_index > n_matches ) + { + return( 0 ); + } + if ( !match_valid[match_index] ) + { + int match_len = match_vectors[(2*match_index)+1]-match_vectors[2*match_index]; + if ( match_lengths[match_index] < (match_len+1) ) + { + delete[] match_buffers[match_index]; + match_buffers[match_index] = new char[match_len+1]; + match_lengths[match_index] = match_len+1; + } + memcpy( match_buffers[match_index], match_string+match_vectors[2*match_index], match_len ); + match_buffers[match_index][match_len] = '\0'; + match_valid[match_index] = true; + } + return( match_buffers[match_index] ); +} + +int RegExpr::MatchLength( int match_index ) const +{ + if ( match_index > n_matches ) + { + return( 0 ); + } + return( match_vectors[(2*match_index)+1]-match_vectors[2*match_index] ); +} + +#endif // HAVE_LIBPCRE diff --git a/src/zm_regexp.h b/src/zm_regexp.h new file mode 100644 index 000000000..f1c9d705d --- /dev/null +++ b/src/zm_regexp.h @@ -0,0 +1,65 @@ +/* + * ZoneMinder Regular Expression Interface, $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. +*/ + +#include "zm.h" + +#ifndef ZM_REGEXP_H +#define ZM_REGEXP_H + +#if HAVE_LIBPCRE + +#if HAVE_PCRE_H +#include +#elif HAVE_PCRE_PCRE_H +#include +#else +#error Unable to locate pcre.h, please do 'locate pcre.h' and report location to zoneminder.com +#endif + +class RegExpr +{ +protected: + pcre *regex; + pcre_extra *regextra; + int max_matches; + int *match_vectors; + mutable char **match_buffers; + int *match_lengths; + bool *match_valid; + +protected: + const char *match_string; + int n_matches; + +protected: + bool ok; + +public: + RegExpr( const char *pattern, int cflags=0, int p_max_matches=32 ); + ~RegExpr(); + bool Ok() const { return( ok ); } + int MatchCount() const { return( n_matches ); } + int Match( const char *subject_string, int subject_length, int flags=0 ); + const char *MatchString( int match_index ) const; + int MatchLength( int match_index ) const; +}; + +#endif // HAVE_LIBPCRE + +#endif // ZM_REGEXP_H diff --git a/src/zm_remote_camera.cpp b/src/zm_remote_camera.cpp new file mode 100644 index 000000000..8c54c0ad7 --- /dev/null +++ b/src/zm_remote_camera.cpp @@ -0,0 +1,75 @@ +// +// ZoneMinder Remote Camera Class Implementation, $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. +// + +#include "zm_remote_camera.h" + +#include "zm_utils.h" + +RemoteCamera::RemoteCamera( int p_id, const std::string &p_protocol, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + Camera( p_id, REMOTE_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ), + protocol( p_protocol ), + host( p_host ), + port( p_port ), + path( p_path ), + hp( 0 ) +{ + if ( path[0] != '/' ) + path = '/'+path; +} + +RemoteCamera::~RemoteCamera() +{ +} + +void RemoteCamera::Initialise() +{ + if( protocol.empty() ) + Fatal( "No protocol specified for remote camera" ); + + if( host.empty() ) + Fatal( "No host specified for remote camera" ); + + if( port.empty() ) + Fatal( "No port specified for remote camera" ); + + //if( path.empty() ) + //Fatal( "No path specified for remote camera" ); + + // Cache as much as we can to speed things up + std::string::size_type authIndex = host.find( '@' ); + + if ( authIndex != std::string::npos ) + { + auth = host.substr( 0, authIndex ); + host.erase( 0, authIndex+1 ); + auth64 = base64Encode( auth ); + } + + if ( !hp ) + { + if ( !(hp = gethostbyname(host.c_str())) ) + { + Fatal( "Can't gethostbyname(%s): %s", host.c_str(), strerror(h_errno) ); + } + memcpy((char *)&sa.sin_addr, (char *)hp->h_addr, hp->h_length); + sa.sin_family = hp->h_addrtype; + sa.sin_port = htons(atoi(port.c_str())); + } +} + diff --git a/src/zm_remote_camera.h b/src/zm_remote_camera.h new file mode 100644 index 000000000..32a331136 --- /dev/null +++ b/src/zm_remote_camera.h @@ -0,0 +1,65 @@ +// +// ZoneMinder Remote Camera Class Interface, $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. +// + +#ifndef ZM_REMOTE_CAMERA_H +#define ZM_REMOTE_CAMERA_H + +#include "zm_camera.h" + +#include +#include + +// +// Class representing 'remote' cameras, i.e. those which are +// accessed over a network connection. +// +class RemoteCamera : public Camera +{ +protected: + std::string protocol; + std::string host; + std::string port; + std::string path; + std::string auth; + std::string auth64; + +protected: + struct hostent *hp; + struct sockaddr_in sa; + +public: + RemoteCamera( int p_id, const std::string &p_proto, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + virtual ~RemoteCamera(); + + const std::string &Protocol() const { return( protocol ); } + const std::string &Host() const { return( host ); } + const std::string &Port() const { return( port ); } + const std::string &Path() const { return( path ); } + const std::string &Auth() const { return( auth ); } + + virtual void Initialise(); + virtual void Terminate() = 0; + virtual int Connect() = 0; + virtual int Disconnect() = 0; + virtual int PreCapture() = 0; + virtual int Capture( Image &image ) = 0; + virtual int PostCapture() = 0; +}; + +#endif // ZM_REMOTE_CAMERA_H diff --git a/src/zm_remote_camera_http.cpp b/src/zm_remote_camera_http.cpp new file mode 100644 index 000000000..e609fc08e --- /dev/null +++ b/src/zm_remote_camera_http.cpp @@ -0,0 +1,1150 @@ +// +// ZoneMinder Remote Camera Class Implementation, $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. +// + +#include "zm_remote_camera_http.h" + +#include "zm_mem_utils.h" + +#include +#include +#include + +RemoteCameraHttp::RemoteCameraHttp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + RemoteCamera( p_id, "http", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ) +{ + sd = -1; + + timeout.tv_sec = 0; + timeout.tv_usec = 0; + + if ( p_method == "simple" ) + method = SIMPLE; + else if ( p_method == "regexp" ) + method = REGEXP; + else + Fatal( "Unrecognised method '%s' when creating HTTP camera %d", p_method.c_str(), id ); + if ( capture ) + { + Initialise(); + } +} + +RemoteCameraHttp::~RemoteCameraHttp() +{ + if ( capture ) + { + Terminate(); + } +} + +void RemoteCameraHttp::Initialise() +{ + RemoteCamera::Initialise(); + + if ( request.empty() ) + { + request = stringtf( "GET %s HTTP/%s\r\n", path.c_str(), config.http_version ); + request += stringtf( "User-Agent: %s/%s\r\n", config.http_ua, ZM_VERSION ); + request += stringtf( "Host: %s\r\n", host .c_str()); + if ( strcmp( config.http_version, "1.0" ) == 0 ) + request += stringtf( "Connection: Keep-Alive\r\n" ); + if ( !auth.empty() ) + request += stringtf( "Authorization: Basic %s\r\n", auth64.c_str() ); + request += "\r\n"; + Debug( 2, "Request: %s", request.c_str() ); + } + + if ( !timeout.tv_sec ) + { + timeout.tv_sec = config.http_timeout/1000; + timeout.tv_usec = (config.http_timeout%1000)*1000; + } + + int max_size = width*height*colours; + + buffer.size( max_size ); + + mode = SINGLE_IMAGE; + format = UNDEF; + state = HEADER; +} + +int RemoteCameraHttp::Connect() +{ + if ( sd < 0 ) + { + sd = socket( hp->h_addrtype, SOCK_STREAM, 0 ); + if ( sd < 0 ) + { + Error( "Can't create socket: %s", strerror(errno) ); + return( -1 ); + } + + if ( connect( sd, (struct sockaddr *)&sa, sizeof(sa) ) < 0 ) + { + Error( "Can't connect to remote camera: %s", strerror(errno) ); + Disconnect(); + return( -1 ); + } + } + Debug( 3, "Connected to host, socket = %d", sd ); + return( sd ); +} + +int RemoteCameraHttp::Disconnect() +{ + close( sd ); + sd = -1; + Debug( 3, "Disconnected from host" ); + return( 0 ); +} + +int RemoteCameraHttp::SendRequest() +{ + if ( write( sd, request.data(), request.length() ) < 0 ) + { + Error( "Can't write: %s", strerror(errno) ); + Disconnect(); + return( -1 ); + } + format = UNDEF; + state = HEADER; + Debug( 3, "Request sent" ); + return( 0 ); +} + +int RemoteCameraHttp::ReadData( Buffer &buffer, int bytes_expected ) +{ + fd_set rfds; + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + + struct timeval temp_timeout = timeout; + + int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); + if( n_found == 0 ) + { + Warning( "Select timed out" ); + Disconnect(); + return( 0 ); + } + else if ( n_found < 0) + { + Error( "Select error: %s", strerror(errno) ); + return( -1 ); + } + + int total_bytes_to_read = 0; + + if ( bytes_expected ) + { + total_bytes_to_read = bytes_expected; + } + else + { + if ( ioctl( sd, FIONREAD, &total_bytes_to_read ) < 0 ) + { + Error( "Can't ioctl(): %s", strerror(errno) ); + return( -1 ); + } + + if ( total_bytes_to_read == 0 ) + { + Debug( 3, "Socket closed" ); + Disconnect(); + return( 0 ); + } + } + Debug( 3, "Expecting %d bytes", total_bytes_to_read ); + + int total_bytes_read = 0; + do + { + static unsigned char temp_buffer[ZM_NETWORK_BUFSIZ]; + int bytes_to_read = (unsigned int)total_bytes_to_read>(unsigned int)sizeof(temp_buffer)?sizeof(temp_buffer):total_bytes_to_read; + int bytes_read = read( sd, temp_buffer, bytes_to_read ); + + if ( bytes_read < 0) + { + Error( "Read error: %s", strerror(errno) ); + return( -1 ); + } + else if ( bytes_read == 0) + { + Debug( 3, "Socket closed" ); + Disconnect(); + return( 0 ); + } + else if ( bytes_read < bytes_to_read ) + { + Error( "Incomplete read, expected %d, got %d", bytes_to_read, bytes_read ); + return( -1 ); + } + Debug( 3, "Read %d bytes", bytes_read ); + buffer.append( temp_buffer, bytes_read ); + total_bytes_read += bytes_read; + total_bytes_to_read -= bytes_read; + } + while ( total_bytes_to_read ); + + return( total_bytes_read ); +} + +int RemoteCameraHttp::GetResponse() +{ +#if HAVE_LIBPCRE + if ( method == REGEXP ) + { + const char *header = 0; + int header_len = 0; + const char *http_version = 0; + int status_code = 0; + const char *status_mesg = 0; + const char *connection_type = ""; + int content_length = 0; + const char *content_type = ""; + const char *content_boundary = ""; + const char *subheader = 0; + int subheader_len = 0; + //int subcontent_length = 0; + //const char *subcontent_type = ""; + + while ( true ) + { + switch( state ) + { + case HEADER : + { + static RegExpr *header_expr = 0; + static RegExpr *status_expr = 0; + static RegExpr *connection_expr = 0; + static RegExpr *content_length_expr = 0; + static RegExpr *content_type_expr = 0; + + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read header data" ); + return( -1 ); + } + if ( !header_expr ) + header_expr = new RegExpr( "^(.+?\r?\n\r?\n)", PCRE_DOTALL ); + if ( header_expr->Match( (char*)buffer, buffer.size() ) == 2 ) + { + header = header_expr->MatchString( 1 ); + header_len = header_expr->MatchLength( 1 ); + Debug( 4, "Captured header (%d bytes):\n'%s'", header_len, header ); + + if ( !status_expr ) + status_expr = new RegExpr( "^HTTP/(1\\.[01]) +([0-9]+) +(.+?)\r?\n", PCRE_CASELESS ); + if ( status_expr->Match( header, header_len ) < 4 ) + { + Error( "Unable to extract HTTP status from header" ); + return( -1 ); + } + http_version = status_expr->MatchString( 1 ); + status_code = atoi( status_expr->MatchString( 2 ) ); + status_mesg = status_expr->MatchString( 3 ); + + if ( status_code < 200 || status_code > 299 ) + { + Error( "Invalid response status %d: %s", status_code, status_mesg ); + return( -1 ); + } + Debug( 3, "Got status '%d' (%s), http version %s", status_code, status_mesg, http_version ); + + if ( !connection_expr ) + connection_expr = new RegExpr( "Connection: ?(.+?)\r?\n", PCRE_CASELESS ); + if ( connection_expr->Match( header, header_len ) == 2 ) + { + connection_type = connection_expr->MatchString( 1 ); + Debug( 3, "Got connection '%s'", connection_type ); + } + + if ( !content_length_expr ) + content_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); + if ( content_length_expr->Match( header, header_len ) == 2 ) + { + content_length = atoi( content_length_expr->MatchString( 1 ) ); + Debug( 3, "Got content length '%d'", content_length ); + } + + if ( !content_type_expr ) + content_type_expr = new RegExpr( "Content-type: ?(.+?)(?:; ?boundary=(.+?))?\r?\n", PCRE_CASELESS ); + if ( content_type_expr->Match( header, header_len ) >= 2 ) + { + content_type = content_type_expr->MatchString( 1 ); + Debug( 3, "Got content type '%s'\n", content_type ); + if ( content_type_expr->MatchCount() > 2 ) + { + content_boundary = content_type_expr->MatchString( 2 ); + Debug( 3, "Got content boundary '%s'", content_boundary ); + } + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = JPEG; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGB; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGBZ; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) + { + // Image stream, so start processing + if ( !content_boundary[0] ) + { + Error( "No content boundary found in header '%s'", header ); + return( -1 ); + } + mode = MULTI_IMAGE; + state = SUBHEADER; + } + //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) + //{ + //// MPEG stream, coming soon! + //} + else + { + Error( "Unrecognised content type '%s'", content_type ); + return( -1 ); + } + buffer.consume( header_len ); + } + else + { + Debug( 3, "Unable to extract header from stream, retrying" ); + //return( -1 ); + } + break; + } + case SUBHEADER : + { + static RegExpr *subheader_expr = 0; + static RegExpr *subcontent_length_expr = 0; + static RegExpr *subcontent_type_expr = 0; + + if ( !subheader_expr ) + { + char subheader_pattern[256] = ""; + snprintf( subheader_pattern, sizeof(subheader_pattern), "^((?:\r?\n){0,2}?(?:--)?%s\r?\n.+?\r?\n\r?\n)", content_boundary ); + subheader_expr = new RegExpr( subheader_pattern, PCRE_DOTALL ); + } + if ( subheader_expr->Match( (char *)buffer, (int)buffer ) == 2 ) + { + subheader = subheader_expr->MatchString( 1 ); + subheader_len = subheader_expr->MatchLength( 1 ); + Debug( 4, "Captured subheader (%d bytes):'%s'", subheader_len, subheader ); + + if ( !subcontent_length_expr ) + subcontent_length_expr = new RegExpr( "Content-length: ?([0-9]+)\r?\n", PCRE_CASELESS ); + if ( subcontent_length_expr->Match( subheader, subheader_len ) == 2 ) + { + content_length = atoi( subcontent_length_expr->MatchString( 1 ) ); + Debug( 3, "Got subcontent length '%d'", content_length ); + } + + if ( !subcontent_type_expr ) + subcontent_type_expr = new RegExpr( "Content-type: ?(.+?)\r?\n", PCRE_CASELESS ); + if ( subcontent_type_expr->Match( subheader, subheader_len ) == 2 ) + { + content_type = subcontent_type_expr->MatchString( 1 ); + Debug( 3, "Got subcontent type '%s'", content_type ); + } + + buffer.consume( subheader_len ); + state = CONTENT; + } + else + { + Debug( 3, "Unable to extract subheader from stream, retrying" ); + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + return( -1 ); + } + } + break; + } + case CONTENT : + { + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + format = JPEG; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + format = X_RGB; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + format = X_RGBZ; + } + else + { + Error( "Found unsupported content type '%s'", content_type ); + return( -1 ); + } + + if ( content_length ) + { + while ( buffer.size() < (unsigned int)content_length ) + { + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read content" ); + return( -1 ); + } + } + Debug( 3, "Got end of image by length, content-length = %d", content_length ); + } + else + { + while ( !content_length ) + { + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + if ( mode == MULTI_IMAGE ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read content" ); + return( -1 ); + } + static RegExpr *content_expr = 0; + if ( buffer_len ) + { + if ( mode == MULTI_IMAGE ) + { + if ( !content_expr ) + { + char content_pattern[256] = ""; + snprintf( content_pattern, sizeof(content_pattern), "^(.+?)(?:\r?\n)*(?:--)?%s\r?\n", content_boundary ); + content_expr = new RegExpr( content_pattern, PCRE_DOTALL ); + } + if ( content_expr->Match( buffer, buffer.size() ) == 2 ) + { + content_length = content_expr->MatchLength( 1 ); + Debug( 3, "Got end of image by pattern, content-length = %d", content_length ); + } + } + } + else + { + content_length = buffer.size(); + Debug( 3, "Got end of image by closure, content-length = %d", content_length ); + if ( mode == SINGLE_IMAGE ) + { + if ( !content_expr ) + { + content_expr = new RegExpr( "^(.+?)(?:\r?\n){1,2}?$", PCRE_DOTALL ); + } + if ( content_expr->Match( buffer, buffer.size() ) == 2 ) + { + content_length = content_expr->MatchLength( 1 ); + Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); + } + } + } + } + } + if ( mode == SINGLE_IMAGE ) + { + state = HEADER; + Disconnect(); + } + else + { + state = SUBHEADER; + } + Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); + return( content_length ); + } + case HEADERCONT : + case SUBHEADERCONT : + { + // Ignore + break; + } + } + } + } + else +#endif // HAVE_LIBPCRE + { + if ( method == REGEXP ) + { + Warning( "Unable to use netcam regexps as not compiled with libpcre" ); + } + static const char *http_match = "HTTP/"; + static const char *connection_match = "Connection:"; + static const char *content_length_match = "Content-length:"; + static const char *content_type_match = "Content-type:"; + static const char *boundary_match = "boundary="; + static int http_match_len = 0; + static int connection_match_len = 0; + static int content_length_match_len = 0; + static int content_type_match_len = 0; + static int boundary_match_len = 0; + + if ( !http_match_len ) + http_match_len = strlen( http_match ); + if ( !connection_match_len ) + connection_match_len = strlen( connection_match ); + if ( !content_length_match_len ) + content_length_match_len = strlen( content_length_match ); + if ( !content_type_match_len ) + content_type_match_len = strlen( content_type_match ); + if ( !boundary_match_len ) + boundary_match_len = strlen( boundary_match ); + + static int n_headers; + //static char *headers[32]; + + static int n_subheaders; + //static char *subheaders[32]; + + static char *http_header; + static char *connection_header; + static char *content_length_header; + static char *content_type_header; + static char *boundary_header; + static char subcontent_length_header[32]; + static char subcontent_type_header[64]; + + static char http_version[16]; + static char status_code[16]; + //static int status; + static char status_mesg[256]; + static char connection_type[32]; + static int content_length; + static char content_type[32]; + static char content_boundary[64]; + static int content_boundary_len; + + while ( true ) + { + switch( state ) + { + case HEADER : + { + n_headers = 0; + http_header = 0; + connection_header = 0; + content_length_header = 0; + content_type_header = 0; + + http_version[0] = '\0'; + status_code [0]= '\0'; + //status = 0; + status_mesg [0]= '\0'; + connection_type [0]= '\0'; + content_length = 0; + content_type[0] = '\0'; + content_boundary[0] = '\0'; + content_boundary_len = 0; + } + case HEADERCONT : + { + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read header" ); + return( -1 ); + } + + char *crlf = 0; + char *header_ptr = (char *)buffer; + int header_len = buffer.size(); + bool all_headers = false; + + while( true ) + { + int crlf_len = memspn( header_ptr, "\r\n", header_len ); + if ( n_headers ) + { + if ( (crlf_len == 2 && !strncmp( header_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( header_ptr, "\r\n\r\n", crlf_len )) ) + { + *header_ptr = '\0'; + header_ptr += crlf_len; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + all_headers = true; + break; + } + } + if ( crlf_len ) + { + if ( header_len == crlf_len ) + { + break; + } + else + { + *header_ptr = '\0'; + header_ptr += crlf_len; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + } + } + + Debug( 6, "%s", header_ptr ); + if ( (crlf = mempbrk( header_ptr, "\r\n", header_len )) ) + { + //headers[n_headers++] = header_ptr; + n_headers++; + + if ( !http_header && (strncasecmp( header_ptr, http_match, http_match_len ) == 0) ) + { + http_header = header_ptr+http_match_len; + Debug( 6, "Got http header '%s'", header_ptr ); + } + else if ( !connection_header && (strncasecmp( header_ptr, connection_match, connection_match_len) == 0) ) + { + connection_header = header_ptr+connection_match_len; + Debug( 6, "Got connection header '%s'", header_ptr ); + } + else if ( !content_length_header && (strncasecmp( header_ptr, content_length_match, content_length_match_len) == 0) ) + { + content_length_header = header_ptr+content_length_match_len; + Debug( 6, "Got content length header '%s'", header_ptr ); + } + else if ( !content_type_header && (strncasecmp( header_ptr, content_type_match, content_type_match_len) == 0) ) + { + content_type_header = header_ptr+content_type_match_len; + Debug( 6, "Got content type header '%s'", header_ptr ); + } + else + { + Debug( 6, "Got ignored header '%s'", header_ptr ); + } + header_ptr = crlf; + header_len -= buffer.consume( header_ptr-(char *)buffer ); + } + else + { + // No end of line found + break; + } + } + + if ( all_headers ) + { + char *start_ptr, *end_ptr; + + if ( !http_header ) + { + Error( "Unable to extract HTTP status from header" ); + return( -1 ); + } + + start_ptr = http_header; + end_ptr = start_ptr+strspn( start_ptr, "10." ); + + memset( http_version, 0, sizeof(http_version) ); + strncpy( http_version, start_ptr, end_ptr-start_ptr ); + + start_ptr = end_ptr; + start_ptr += strspn( start_ptr, " " ); + end_ptr = start_ptr+strspn( start_ptr, "0123456789" ); + + memset( status_code, 0, sizeof(status_code) ); + strncpy( status_code, start_ptr, end_ptr-start_ptr ); + int status = atoi( status_code ); + + start_ptr = end_ptr; + start_ptr += strspn( start_ptr, " " ); + strcpy( status_mesg, start_ptr ); + + if ( status < 200 || status > 299 ) + { + Error( "Invalid response status %s: %s", status_code, status_mesg ); + return( -1 ); + } + Debug( 3, "Got status '%d' (%s), http version %s", status, status_mesg, http_version ); + + if ( connection_header ) + { + memset( connection_type, 0, sizeof(connection_type) ); + start_ptr = connection_header + strspn( connection_header, " " ); + strcpy( connection_type, start_ptr ); + Debug( 3, "Got connection '%s'", connection_type ); + } + if ( content_length_header ) + { + start_ptr = content_length_header + strspn( content_length_header, " " ); + content_length = atoi( start_ptr ); + Debug( 3, "Got content length '%d'", content_length ); + } + if ( content_type_header ) + { + memset( content_type, 0, sizeof(content_type) ); + start_ptr = content_type_header + strspn( content_type_header, " " ); + if ( (end_ptr = strchr( start_ptr, ';' )) ) + { + strncpy( content_type, start_ptr, end_ptr-start_ptr ); + Debug( 3, "Got content type '%s'", content_type ); + + start_ptr = end_ptr + strspn( end_ptr, "; " ); + + if ( strncasecmp( start_ptr, boundary_match, boundary_match_len ) == 0 ) + { + start_ptr += boundary_match_len; + start_ptr += strspn( start_ptr, "-" ); + content_boundary_len = sprintf( content_boundary, "--%s", start_ptr ); + Debug( 3, "Got content boundary '%s'", content_boundary ); + } + else + { + Error( "No content boundary found in header '%s'", content_type_header ); + } + } + else + { + strcpy( content_type, start_ptr ); + Debug( 3, "Got content type '%s'", content_type ); + } + } + + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = JPEG; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGB; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + // Single image + mode = SINGLE_IMAGE; + format = X_RGBZ; + state = CONTENT; + } + else if ( !strcasecmp( content_type, "multipart/x-mixed-replace" ) ) + { + // Image stream, so start processing + if ( !content_boundary[0] ) + { + Error( "No content boundary found in header '%s'", content_type_header ); + return( -1 ); + } + mode = MULTI_IMAGE; + state = SUBHEADER; + } + //else if ( !strcasecmp( content_type, "video/mpeg" ) || !strcasecmp( content_type, "video/mpg" ) ) + //{ + //// MPEG stream, coming soon! + //} + else + { + Error( "Unrecognised content type '%s'", content_type ); + return( -1 ); + } + } + else + { + Debug( 3, "Unable to extract entire header from stream, continuing" ); + state = HEADERCONT; + //return( -1 ); + } + break; + } + case SUBHEADER : + { + n_subheaders = 0; + boundary_header = 0; + subcontent_length_header[0] = '\0'; + subcontent_type_header[0] = '\0'; + content_length = 0; + content_type[0] = '\0'; + } + case SUBHEADERCONT : + { + char *crlf = 0; + char *subheader_ptr = (char *)buffer; + int subheader_len = buffer.size(); + bool all_headers = false; + + while( true ) + { + int crlf_len = memspn( subheader_ptr, "\r\n", subheader_len ); + if ( n_subheaders ) + { + if ( (crlf_len == 2 && !strncmp( subheader_ptr, "\n\n", crlf_len )) || (crlf_len == 4 && !strncmp( subheader_ptr, "\r\n\r\n", crlf_len )) ) + { + *subheader_ptr = '\0'; + subheader_ptr += crlf_len; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + all_headers = true; + break; + } + } + if ( crlf_len ) + { + if ( subheader_len == crlf_len ) + { + break; + } + else + { + *subheader_ptr = '\0'; + subheader_ptr += crlf_len; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + } + } + + Debug( 6, "%d: %s", subheader_len, subheader_ptr ); + + if ( (crlf = mempbrk( subheader_ptr, "\r\n", subheader_len )) ) + { + //subheaders[n_subheaders++] = subheader_ptr; + n_subheaders++; + + if ( !boundary_header && (strncasecmp( subheader_ptr, content_boundary, content_boundary_len ) == 0) ) + { + boundary_header = subheader_ptr; + Debug( 4, "Got boundary subheader '%s'", subheader_ptr ); + } + else if ( !subcontent_length_header[0] && (strncasecmp( subheader_ptr, content_length_match, content_length_match_len) == 0) ) + { + strncpy( subcontent_length_header, subheader_ptr+content_length_match_len, sizeof(subcontent_length_header) ); + *(subcontent_length_header+strcspn( subcontent_length_header, "\r\n" )) = '\0'; + Debug( 4, "Got content length subheader '%s'", subcontent_length_header ); + } + else if ( !subcontent_type_header[0] && (strncasecmp( subheader_ptr, content_type_match, content_type_match_len) == 0) ) + { + strncpy( subcontent_type_header, subheader_ptr+content_type_match_len, sizeof(subcontent_type_header) ); + *(subcontent_type_header+strcspn( subcontent_type_header, "\r\n" )) = '\0'; + Debug( 4, "Got content type subheader '%s'", subcontent_type_header ); + } + else + { + Debug( 6, "Got ignored subheader '%s' found", subheader_ptr ); + } + subheader_ptr = crlf; + subheader_len -= buffer.consume( subheader_ptr-(char *)buffer ); + } + else + { + // No line end found + break; + } + } + + if ( all_headers && boundary_header ) + { + char *start_ptr/*, *end_ptr*/; + + Debug( 3, "Got boundary '%s'", boundary_header ); + + if ( subcontent_length_header[0] ) + { + start_ptr = subcontent_length_header + strspn( subcontent_length_header, " " ); + content_length = atoi( start_ptr ); + Debug( 3, "Got subcontent length '%d'", content_length ); + } + if ( subcontent_type_header[0] ) + { + memset( content_type, 0, sizeof(content_type) ); + start_ptr = subcontent_type_header + strspn( subcontent_type_header, " " ); + strcpy( content_type, start_ptr ); + Debug( 3, "Got subcontent type '%s'", content_type ); + } + state = CONTENT; + } + else + { + Debug( 3, "Unable to extract subheader from stream, retrying" ); + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read subheader" ); + return( -1 ); + } + state = SUBHEADERCONT; + } + break; + } + case CONTENT : + { + if ( !strcasecmp( content_type, "image/jpeg" ) || !strcasecmp( content_type, "image/jpg" ) ) + { + format = JPEG; + } + else if ( !strcasecmp( content_type, "image/x-rgb" ) ) + { + format = X_RGB; + } + else if ( !strcasecmp( content_type, "image/x-rgbz" ) ) + { + format = X_RGBZ; + } + else + { + Error( "Found unsupported content type '%s'", content_type ); + return( -1 ); + } + + if ( format == JPEG && buffer.size() >= 2 ) + { + if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) + { + Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); + return( -1 ); + } + } + + if ( content_length ) + { + while ( buffer.size() < (unsigned int)content_length ) + { + //int buffer_len = ReadData( buffer, content_length-buffer.size() ); + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read content" ); + return( -1 ); + } + } + Debug( 3, "Got end of image by length, content-length = %d", content_length ); + } + else + { + int content_pos = 0; + while ( !content_length ) + { + int buffer_len = ReadData( buffer ); + if ( buffer_len == 0 ) + { + if ( mode == MULTI_IMAGE ) + { + Error( "Connection dropped by remote end" ); + return( 0 ); + } + } + else if ( buffer_len < 0 ) + { + Error( "Unable to read content" ); + return( -1 ); + } + int buffer_size = buffer.size(); + if ( buffer_len ) + { + if ( mode == MULTI_IMAGE ) + { + while ( char *start_ptr = (char *)memstr( (char *)buffer+content_pos, "\r\n--", buffer_size-content_pos ) ) + { + content_length = start_ptr - (char *)buffer; + Debug( 3, "Got end of image by pattern (crlf--), content-length = %d", content_length ); + break; + } + } + } + else + { + content_length = buffer_size; + Debug( 3, "Got end of image by closure, content-length = %d", content_length ); + if ( mode == SINGLE_IMAGE ) + { + char *end_ptr = (char *)buffer+buffer_size; + + while( *end_ptr == '\r' || *end_ptr == '\n' ) + { + content_length--; + end_ptr--; + } + + if ( end_ptr != ((char *)buffer+buffer_size) ) + { + Debug( 3, "Trimmed end of image, new content-length = %d", content_length ); + } + } + } + } + } + if ( mode == SINGLE_IMAGE ) + { + state = HEADER; + Disconnect(); + } + else + { + state = SUBHEADER; + } + + if ( format == JPEG && buffer.size() >= 2 ) + { + if ( buffer[0] != 0xff || buffer[1] != 0xd8 ) + { + Error( "Found bogus jpeg header '%02x%02x'", buffer[0], buffer[1] ); + return( -1 ); + } + } + + Debug( 3, "Returning %d (%d) bytes of captured content", content_length, buffer.size() ); + return( content_length ); + } + } + } + } + return( 0 ); +} + +int RemoteCameraHttp::PreCapture() +{ + if ( sd < 0 ) + { + Connect(); + if ( sd < 0 ) + { + Error( "Unable to connect to camera" ); + return( -1 ); + } + mode = SINGLE_IMAGE; + buffer.clear(); + } + if ( mode == SINGLE_IMAGE ) + { + if ( SendRequest() < 0 ) + { + Error( "Unable to send request" ); + Disconnect(); + return( -1 ); + } + } + return( 0 ); +} + +int RemoteCameraHttp::Capture( Image &image ) +{ + int content_length = GetResponse(); + if ( content_length == 0 ) + { + Warning( "Unable to capture image, retrying" ); + return( 1 ); + } + if ( content_length < 0 ) + { + Error( "Unable to get response" ); + Disconnect(); + return( -1 ); + } + switch( format ) + { + case JPEG : + { + if ( !image.DecodeJpeg( buffer.extract( content_length ), content_length, colours, subpixelorder ) ) + { + Error( "Unable to decode jpeg" ); + Disconnect(); + return( -1 ); + } + break; + } + case X_RGB : + { + if ( content_length != image.Size() ) + { + Error( "Image length mismatch, expected %d bytes, content length was %d", image.Size(), content_length ); + Disconnect(); + return( -1 ); + } + image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); + break; + } + case X_RGBZ : + { + if ( !image.Unzip( buffer.extract( content_length ), content_length ) ) + { + Error( "Unable to unzip RGB image" ); + Disconnect(); + return( -1 ); + } + image.Assign( width, height, colours, subpixelorder, buffer, imagesize ); + break; + } + default : + { + Error( "Unexpected image format encountered" ); + Disconnect(); + return( -1 ); + } + } + return( 0 ); +} + +int RemoteCameraHttp::PostCapture() +{ + return( 0 ); +} diff --git a/src/zm_remote_camera_http.h b/src/zm_remote_camera_http.h new file mode 100644 index 000000000..0b161247a --- /dev/null +++ b/src/zm_remote_camera_http.h @@ -0,0 +1,63 @@ +// +// ZoneMinder Remote HTTP Camera Class Interface, $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. +// + +#ifndef ZM_REMOTE_CAMERA_HTTP_H +#define ZM_REMOTE_CAMERA_HTTP_H + +#include "zm_remote_camera.h" + +#include "zm_buffer.h" +#include "zm_regexp.h" +#include "zm_utils.h" + +// +// Class representing 'remote' cameras, i.e. those which are +// accessed over a network connection. +// +class RemoteCameraHttp : public RemoteCamera +{ +protected: + std::string request; + struct timeval timeout; + //struct hostent *hp; + //struct sockaddr_in sa; + int sd; + Buffer buffer; + enum { SINGLE_IMAGE, MULTI_IMAGE } mode; + enum { UNDEF, JPEG, X_RGB, X_RGBZ } format; + enum { HEADER, HEADERCONT, SUBHEADER, SUBHEADERCONT, CONTENT } state; + enum { SIMPLE, REGEXP } method; + +public: + RemoteCameraHttp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~RemoteCameraHttp(); + + void Initialise(); + void Terminate() { Disconnect(); } + int Connect(); + int Disconnect(); + int SendRequest(); + int ReadData( Buffer &buffer, int bytes_expected=0 ); + int GetResponse(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); +}; + +#endif // ZM_REMOTE_CAMERA_HTTP_H diff --git a/src/zm_remote_camera_rtsp.cpp b/src/zm_remote_camera_rtsp.cpp new file mode 100644 index 000000000..e352589f6 --- /dev/null +++ b/src/zm_remote_camera_rtsp.cpp @@ -0,0 +1,326 @@ +// +// ZoneMinder Remote Camera Class Implementation, $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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_remote_camera_rtsp.h" +#include "zm_ffmpeg.h" +#include "zm_mem_utils.h" + +#include +#include + +RemoteCameraRtsp::RemoteCameraRtsp( int p_id, const std::string &p_method, const std::string &p_host, const std::string &p_port, const std::string &p_path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) : + RemoteCamera( p_id, "rtsp", p_host, p_port, p_path, p_width, p_height, p_colours, p_brightness, p_contrast, p_hue, p_colour, p_capture ), + rtspThread( 0 ) +{ + if ( p_method == "rtpUni" ) + method = RtspThread::RTP_UNICAST; + else if ( p_method == "rtpMulti" ) + method = RtspThread::RTP_MULTICAST; + else if ( p_method == "rtpRtsp" ) + method = RtspThread::RTP_RTSP; + else if ( p_method == "rtpRtspHttp" ) + method = RtspThread::RTP_RTSP_HTTP; + else + Fatal( "Unrecognised method '%s' when creating RTSP camera %d", p_method.c_str(), id ); + + if ( capture ) + { + Initialise(); + } + + mFormatContext = NULL; + mVideoStreamId = -1; + mCodecContext = NULL; + mCodec = NULL; + mRawFrame = NULL; + mFrame = NULL; + frameCount = 0; + +#if HAVE_LIBSWSCALE + mConvertContext = NULL; +#endif + /* Has to be located inside the constructor so other components such as zma will receive correct colours and subpixel order */ + if(colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = PIX_FMT_RGBA; + } else if(colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = PIX_FMT_RGB24; + } else if(colours == ZM_COLOUR_GRAY8) { + subpixelorder = ZM_SUBPIX_ORDER_NONE; + imagePixFormat = PIX_FMT_GRAY8; + } else { + Panic("Unexpected colours: %d",colours); + } + +} + +RemoteCameraRtsp::~RemoteCameraRtsp() +{ + av_freep( &mFrame ); + av_freep( &mRawFrame ); + +#if HAVE_LIBSWSCALE + if ( mConvertContext ) + { + sws_freeContext( mConvertContext ); + mConvertContext = NULL; + } +#endif + + if ( mCodecContext ) + { + avcodec_close( mCodecContext ); + mCodecContext = NULL; // Freed by av_close_input_file + } + + if ( capture ) + { + Terminate(); + } +} + +void RemoteCameraRtsp::Initialise() +{ + RemoteCamera::Initialise(); + + int max_size = width*height*colours; + + buffer.size( max_size ); + + if ( logDebugging() ) + av_log_set_level( AV_LOG_DEBUG ); + else + av_log_set_level( AV_LOG_QUIET ); + + av_register_all(); + + Connect(); +} + +void RemoteCameraRtsp::Terminate() +{ + Disconnect(); +} + +int RemoteCameraRtsp::Connect() +{ + rtspThread = new RtspThread( id, method, protocol, host, port, path, auth ); + + rtspThread->start(); + + return( 0 ); +} + +int RemoteCameraRtsp::Disconnect() +{ + if ( rtspThread ) + { + rtspThread->stop(); + rtspThread->join(); + delete rtspThread; + rtspThread = 0; + } + return( 0 ); +} + +int RemoteCameraRtsp::PrimeCapture() +{ + Debug( 2, "Waiting for sources" ); + for ( int i = 0; i < 100 && !rtspThread->hasSources(); i++ ) + { + usleep( 100000 ); + } + if ( !rtspThread->hasSources() ) + Fatal( "No RTSP sources" ); + + Debug( 2, "Got sources" ); + + mFormatContext = rtspThread->getFormatContext(); + + // Find first video stream present + mVideoStreamId = -1; + + for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) +#else + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) +#endif + { + mVideoStreamId = i; + break; + } + if ( mVideoStreamId == -1 ) + Fatal( "Unable to locate video stream" ); + + // Get a pointer to the codec context for the video stream + mCodecContext = mFormatContext->streams[mVideoStreamId]->codec; + + // Find the decoder for the video stream + mCodec = avcodec_find_decoder( mCodecContext->codec_id ); + if ( mCodec == NULL ) + Panic( "Unable to locate codec %d decoder", mCodecContext->codec_id ); + + // Open codec +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 7, 0) + if ( avcodec_open( mCodecContext, mCodec ) < 0 ) +#else + if ( avcodec_open2( mCodecContext, mCodec, 0 ) < 0 ) +#endif + Panic( "Can't open codec" ); + + // Allocate space for the native video frame + mRawFrame = avcodec_alloc_frame(); + + // Allocate space for the converted video frame + mFrame = avcodec_alloc_frame(); + + if(mRawFrame == NULL || mFrame == NULL) + Fatal( "Unable to allocate frame(s)"); + + int pSize = avpicture_get_size( imagePixFormat, width, height ); + if( (unsigned int)pSize != imagesize) { + Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize); + } + +#if HAVE_LIBSWSCALE + if(!sws_isSupportedInput(mCodecContext->pix_fmt)) { + Fatal("swscale does not support the codec format: %c%c%c%c",(mCodecContext->pix_fmt)&0xff,((mCodecContext->pix_fmt>>8)&0xff),((mCodecContext->pix_fmt>>16)&0xff),((mCodecContext->pix_fmt>>24)&0xff)); + } + + if(!sws_isSupportedOutput(imagePixFormat)) { + Fatal("swscale does not support the target format: %c%c%c%c",(imagePixFormat)&0xff,((imagePixFormat>>8)&0xff),((imagePixFormat>>16)&0xff),((imagePixFormat>>24)&0xff)); + } + +#else // HAVE_LIBSWSCALE + Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); +#endif // HAVE_LIBSWSCALE + + + return( 0 ); +} + +int RemoteCameraRtsp::PreCapture() +{ + if ( !rtspThread->isRunning() ) + return( -1 ); + if ( !rtspThread->hasSources() ) + { + Error( "Cannot precapture, no RTP sources" ); + return( -1 ); + } + return( 0 ); +} + +int RemoteCameraRtsp::Capture( Image &image ) +{ + AVPacket packet; + uint8_t* directbuffer; + int frameComplete = false; + + /* Request a writeable buffer of the target image */ + directbuffer = image.WriteBuffer(width, height, colours, subpixelorder); + if(directbuffer == NULL) { + Error("Failed requesting writeable buffer for the captured image."); + return (-1); + } + + while ( true ) + { + buffer.clear(); + if ( !rtspThread->isRunning() ) + return (-1); + + if ( rtspThread->getFrame( buffer ) ) + { + Debug( 3, "Read frame %d bytes", buffer.size() ); + Debug( 4, "Address %p", buffer.head() ); + Hexdump( 4, buffer.head(), 16 ); + + if ( !buffer.size() ) + return( -1 ); + + av_init_packet( &packet ); + + while ( !frameComplete && buffer.size() > 0 ) + { + packet.data = buffer.head(); + packet.size = buffer.size(); + int len = avcodec_decode_video2( mCodecContext, mRawFrame, &frameComplete, &packet ); + if ( len < 0 ) + { + Error( "Error while decoding frame %d", frameCount ); + Hexdump( Logger::ERROR, buffer.head(), buffer.size()>256?256:buffer.size() ); + buffer.clear(); + continue; + } + Debug( 2, "Frame: %d - %d/%d", frameCount, len, buffer.size() ); + //if ( buffer.size() < 400 ) + //Hexdump( 0, buffer.head(), buffer.size() ); + + buffer -= len; + + } + if ( frameComplete ) { + + Debug( 3, "Got frame %d", frameCount ); + + avpicture_fill( (AVPicture *)mFrame, directbuffer, imagePixFormat, width, height); + +#if HAVE_LIBSWSCALE + if(mConvertContext == NULL) { + if(config.cpu_extensions && sseversion >= 20) { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL ); + } else { + mConvertContext = sws_getContext( mCodecContext->width, mCodecContext->height, mCodecContext->pix_fmt, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL ); + } + if(mConvertContext == NULL) + Fatal( "Unable to create conversion context"); + } + + if ( sws_scale( mConvertContext, mRawFrame->data, mRawFrame->linesize, 0, mCodecContext->height, mFrame->data, mFrame->linesize ) < 0 ) + Fatal( "Unable to convert raw format %u to target format %u at frame %d", mCodecContext->pix_fmt, imagePixFormat, frameCount ); +#else // HAVE_LIBSWSCALE + Fatal( "You must compile ffmpeg with the --enable-swscale option to use RTSP cameras" ); +#endif // HAVE_LIBSWSCALE + + frameCount++; + + } /* frame complete */ + + av_free_packet( &packet ); + } /* getFrame() */ + + if(frameComplete) + return (0); + + } + return (0) ; +} + +int RemoteCameraRtsp::PostCapture() +{ + return( 0 ); +} +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_remote_camera_rtsp.h b/src/zm_remote_camera_rtsp.h new file mode 100644 index 000000000..3295c9363 --- /dev/null +++ b/src/zm_remote_camera_rtsp.h @@ -0,0 +1,80 @@ +// +// ZoneMinder Remote RTSP Camera Class Interface, $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. +// + +#ifndef ZM_REMOTE_CAMERA_RTSP_H +#define ZM_REMOTE_CAMERA_RTSP_H + +#include "zm_remote_camera.h" + +#include "zm_buffer.h" +#include "zm_utils.h" +#include "zm_rtsp.h" +#include "zm_ffmpeg.h" + +// +// Class representing 'remote' cameras, i.e. those which are +// accessed over a network connection. +// +class RemoteCameraRtsp : public RemoteCamera +{ +protected: + struct sockaddr_in rtsp_sa; + struct sockaddr_in rtcp_sa; + int rtsp_sd; + int rtp_sd; + int rtcp_sd; + + Buffer buffer; + + RtspThread::RtspMethod method; + + RtspThread *rtspThread; + + int frameCount; + +#if HAVE_LIBAVFORMAT + AVFormatContext *mFormatContext; + int mVideoStreamId; + AVCodecContext *mCodecContext; + AVCodec *mCodec; + AVFrame *mRawFrame; + AVFrame *mFrame; + PixelFormat imagePixFormat; +#endif // HAVE_LIBAVFORMAT + +#if HAVE_LIBSWSCALE + struct SwsContext *mConvertContext; +#endif + +public: + RemoteCameraRtsp( int p_id, const std::string &method, const std::string &host, const std::string &port, const std::string &path, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ); + ~RemoteCameraRtsp(); + + void Initialise(); + void Terminate(); + int Connect(); + int Disconnect(); + + int PrimeCapture(); + int PreCapture(); + int Capture( Image &image ); + int PostCapture(); +}; + +#endif // ZM_REMOTE_CAMERA_RTSP_H diff --git a/src/zm_rgb.h b/src/zm_rgb.h new file mode 100644 index 000000000..bfef10501 --- /dev/null +++ b/src/zm_rgb.h @@ -0,0 +1,157 @@ +// +// ZoneMinder RGB Interface, $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. +// + +#ifndef ZM_RGB_H +#define ZM_RGB_H + +typedef uint32_t Rgb; // RGB colour type + +#define WHITE 0xff +#define WHITE_R 0xff +#define WHITE_G 0xff +#define WHITE_B 0xff + +#define BLACK 0x00 +#define BLACK_R 0x00 +#define BLACK_G 0x00 +#define BLACK_B 0x00 + +#define RGB_WHITE (0x00ffffff) +#define RGB_BLACK (0x00000000) +#define RGB_RED (0x000000ff) +#define RGB_GREEN (0x0000ff00) +#define RGB_BLUE (0x00ff0000) +#define RGB_ORANGE (0x0000a5ff) +#define RGB_PURPLE (0x00800080) +#define RGB_TRANSPARENT (0x01000000) + +#define RGB_VAL(v,c) (((v)>>(16-((c)*8)))&0xff) + +/* RGB or RGBA macros */ +#define BLUE_VAL_RGBA(v) (((v)>>16)&0xff) +#define GREEN_VAL_RGBA(v) (((v)>>8)&0xff) +#define RED_VAL_RGBA(v) ((v)&0xff) +#define ALPHA_VAL_RGBA(v) ((v)>>24)&0xff) +#define RED_PTR_RGBA(ptr) (*((uint8_t*)ptr)) +#define GREEN_PTR_RGBA(ptr) (*((uint8_t*)ptr+1)) +#define BLUE_PTR_RGBA(ptr) (*((uint8_t*)ptr+2)) +#define ALPHA_PTR_RGBA(ptr) (*((uint8_t*)ptr+3)) + +/* BGR or BGRA */ +#define RED_VAL_BGRA(v) (((v)>>16)&0xff) +#define GREEN_VAL_BGRA(v) (((v)>>8)&0xff) +#define BLUE_VAL_BGRA(v) ((v)&0xff) +#define ALPHA_VAL_BGRA(v) ((v)>>24)&0xff) +#define RED_PTR_BGRA(ptr) (*((uint8_t*)ptr+2)) +#define GREEN_PTR_BGRA(ptr) (*((uint8_t*)ptr+1)) +#define BLUE_PTR_BGRA(ptr) (*((uint8_t*)ptr)) +#define ALPHA_PTR_BGRA(ptr) (*((uint8_t*)ptr+3)) + +/* ARGB */ +#define BLUE_VAL_ARGB(v) (((v)>>24)&0xff) +#define GREEN_VAL_ARGB(v) (((v)>>16)&0xff) +#define RED_VAL_ARGB(v) (((v)>>8)&0xff) +#define ALPHA_VAL_ARGB(v) ((v)&0xff) +#define RED_PTR_ARGB(ptr) (*((uint8_t*)ptr+1)) +#define GREEN_PTR_ARGB(ptr) (*((uint8_t*)ptr+2)) +#define BLUE_PTR_ARGB(ptr) (*((uint8_t*)ptr+3)) +#define ALPHA_PTR_ARGB(ptr) (*((uint8_t*)ptr)) + +/* ABGR */ +#define BLUE_VAL_ABGR(v) (((v)>>8)&0xff) +#define GREEN_VAL_ABGR(v) (((v)>>16)&0xff) +#define RED_VAL_ABGR(v) (((v)>>24)&0xff) +#define ALPHA_VAL_ABGR(v) ((v)&0xff) +#define RED_PTR_ABGR(ptr) (*((uint8_t*)ptr+3)) +#define GREEN_PTR_ABGR(ptr) (*((uint8_t*)ptr+2)) +#define BLUE_PTR_ABGR(ptr) (*((uint8_t*)ptr+1)) +#define ALPHA_PTR_ABGR(ptr) (*((uint8_t*)ptr)) + + +#define RGBA_BGRA_ZEROALPHA(v) ((v)&0x00ffffff) +#define ARGB_ABGR_ZEROALPHA(v) ((v)&0xffffff00) + +/* ITU-R BT.709: Y = (0.2126 * R) + (0.7152 * G) + (0.0722 * B) */ +/* ITU-R BT.601: Y = (0.299 * R) + (0.587 * G) + (0.114 * B) */ +/* The formulas below produce an almost identical result to the weighted algorithms from the ITU-R BT.601 standard and the newer ITU-R BT.709 standard, but a lot faster */ +// #define RGB_FASTLUM_SINGLE_ITU709(v) ((RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) +// #define RGB_FASTLUM_VALUES_ITU709(ra,ga,ba) (((ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga)+(ga))>>3) +// #define RGB_FASTLUM_SINGLE_ITU601(v) ((RED(v)+RED(v)+RED(v)+BLUE(v)+GREEN(v)+GREEN(v)+GREEN(v)+GREEN(v))>>3) +// #define RGB_FASTLUM_VALUES_ITU601(ra,ga,ba) (((ra)+(ra)+(ra)+(ba)+(ga)+(ga)+(ga)+(ga))>>3) + +/* ZM colours */ +#define ZM_COLOUR_RGB32 4 +#define ZM_COLOUR_RGB24 3 +#define ZM_COLOUR_GRAY8 1 + +/* Subpixel ordering */ +/* Based on byte order naming. For example, for ARGB (on both little endian or big endian) byte+0 should be alpha, byte+1 should be red, and so on. */ +#define ZM_SUBPIX_ORDER_NONE 2 +#define ZM_SUBPIX_ORDER_RGB 6 +#define ZM_SUBPIX_ORDER_BGR 5 +#define ZM_SUBPIX_ORDER_BGRA 7 +#define ZM_SUBPIX_ORDER_RGBA 8 +#define ZM_SUBPIX_ORDER_ABGR 9 +#define ZM_SUBPIX_ORDER_ARGB 10 + +/* A macro to use default subpixel order for a specified colour. */ +/* for grayscale it will use NONE, for 3 colours it will use R,G,B, for 4 colours it will use R,G,B,A */ +#define ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(c) ((c)<<1) + +/* Convert RGB colour value into BGR\ARGB\ABGR */ +inline Rgb rgb_convert(Rgb p_col, int p_subpixorder) { + Rgb result; + + switch(p_subpixorder) { + + case ZM_SUBPIX_ORDER_BGR: + case ZM_SUBPIX_ORDER_BGRA: + { + BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col); + } + break; + case ZM_SUBPIX_ORDER_ARGB: + { + BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col); + } + break; + case ZM_SUBPIX_ORDER_ABGR: + { + BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col); + GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col); + RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col); + } + break; + /* Grayscale */ + case ZM_SUBPIX_ORDER_NONE: + result = p_col & 0xff; + break; + default: + return p_col; + break; + } + + return result; +} + +#endif // ZM_RGB_H diff --git a/src/zm_rtp.cpp b/src/zm_rtp.cpp new file mode 100644 index 000000000..2ce21db5a --- /dev/null +++ b/src/zm_rtp.cpp @@ -0,0 +1,22 @@ +// +// ZoneMinder RTP/RTCP Class Implementation, $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. +// + +#include "zm_rtp.h" + +// Blank diff --git a/src/zm_rtp.h b/src/zm_rtp.h new file mode 100644 index 000000000..6fbeeabe6 --- /dev/null +++ b/src/zm_rtp.h @@ -0,0 +1,27 @@ +// +// ZoneMinder RTP/RTCP Class Interface, $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. +// + +#ifndef ZM_RTP_H +#define ZM_RTP_H + +#include "zm.h" + +#define RTP_VERSION 2 + +#endif // ZM_RTP_H diff --git a/src/zm_rtp_ctrl.cpp b/src/zm_rtp_ctrl.cpp new file mode 100644 index 000000000..1d88482d4 --- /dev/null +++ b/src/zm_rtp_ctrl.cpp @@ -0,0 +1,344 @@ +// +// ZoneMinder RTCP Class Implementation, $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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_rtp_ctrl.h" + +#include "zm_time.h" +#include "zm_rtsp.h" + +#include + +RtpCtrlThread::RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ) : mRtspThread( rtspThread ), mRtpSource( rtpSource ), mStop( false ) +{ +} + +int RtpCtrlThread::recvPacket( const unsigned char *packet, ssize_t packetLen ) +{ + const RtcpPacket *rtcpPacket; + rtcpPacket = (RtcpPacket *)packet; + + int consumed = 0; + + //printf( "C: " ); + //for ( int i = 0; i < packetLen; i++ ) + //printf( "%02x ", (unsigned char)packet[i] ); + //printf( "\n" ); + int ver = rtcpPacket->header.version; + int count = rtcpPacket->header.count; + int pt = rtcpPacket->header.pt; + int len = ntohs(rtcpPacket->header.lenN); + + Debug( 5, "RTCP Ver: %d", ver ); + Debug( 5, "RTCP Count: %d", count ); + Debug( 5, "RTCP Pt: %d", pt ); + Debug( 5, "RTCP len: %d", len ); + + switch( pt ) + { + case RTCP_SR : + { + uint32_t ssrc = ntohl(rtcpPacket->body.sr.ssrcN); + + Debug( 5, "RTCP Got SR (%x)", ssrc ); + if ( mRtpSource.getSsrc() ) + { + if ( ssrc != mRtpSource.getSsrc() ) + { + Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); + return( -1 ); + } + } + else if ( ssrc ) + { + mRtpSource.setSsrc( ssrc ); + } + + if ( len > 1 ) + { + //printf( "NTPts:%d.%d, RTPts:%d\n", $ntptsmsb, $ntptslsb, $rtpts ); + uint16_t ntptsmsb = ntohl(rtcpPacket->body.sr.ntpSecN); + uint16_t ntptslsb = ntohl(rtcpPacket->body.sr.ntpFracN); + //printf( "NTPts:%x.%04x, RTPts:%x\n", $ntptsmsb, $ntptslsb, $rtpts ); + //printf( "Pkts:$sendpkts, Octs:$sendocts\n" ); + uint32_t rtpTime = ntohl(rtcpPacket->body.sr.rtpTsN); + + mRtpSource.updateRtcpData( ntptsmsb, ntptslsb, rtpTime ); + } + break; + } + case RTCP_SDES : + { + ssize_t contentLen = packetLen - sizeof(rtcpPacket->header); + while ( contentLen ) + { + Debug( 5, "RTCP CL: %zd", contentLen ); + uint32_t ssrc = ntohl(rtcpPacket->body.sdes.srcN); + + Debug( 5, "RTCP Got SDES (%x), %d items", ssrc, count ); + if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) + { + Warning( "Discarding packet for unrecognised ssrc %x", ssrc ); + return( -1 ); + } + + unsigned char *sdesPtr = (unsigned char *)&rtcpPacket->body.sdes.item; + for ( int i = 0; i < count; i++ ) + { + RtcpSdesItem *item = (RtcpSdesItem *)sdesPtr; + Debug( 5, "RTCP Item length %d", item->len ); + switch( item->type ) + { + case RTCP_SDES_CNAME : + { + std::string cname( item->data, item->len ); + Debug( 5, "RTCP Got CNAME %s", cname.c_str() ); + break; + } + case RTCP_SDES_END : + case RTCP_SDES_NAME : + case RTCP_SDES_EMAIL : + case RTCP_SDES_PHONE : + case RTCP_SDES_LOC : + case RTCP_SDES_TOOL : + case RTCP_SDES_NOTE : + case RTCP_SDES_PRIV : + default : + { + Error( "Received unexpected SDES item type %d, ignoring", item->type ); + return( -1 ); + } + } + int paddedLen = 4+2+item->len+1; // Add null byte + paddedLen = (((paddedLen-1)/4)+1)*4; + Debug( 5, "RTCP PL:%d", paddedLen ); + sdesPtr += paddedLen; + contentLen -= paddedLen; + } + } + break; + } + case RTCP_BYE : + { + Debug( 5, "RTCP Got BYE" ); + mStop = true; + break; + } + case RTCP_RR : + case RTCP_APP : + default : + { + Error( "Received unexpected packet type %d, ignoring", pt ); + return( -1 ); + } + } + consumed = sizeof(uint32_t)*(len+1); + return( consumed ); +} + +int RtpCtrlThread::generateRr( const unsigned char *packet, ssize_t packetLen ) +{ + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.rr)+sizeof(rtcpPacket->body.rr.rr[0]); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_RR; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); + + mRtpSource.updateRtcpStats(); + + Debug( 5, "Ssrc = %d", mRtspThread.getSsrc() ); + Debug( 5, "Ssrc_1 = %d", mRtpSource.getSsrc() ); + Debug( 5, "Last Seq = %d", mRtpSource.getMaxSeq() ); + Debug( 5, "Jitter = %d", mRtpSource.getJitter() ); + Debug( 5, "Last SR = %d", mRtpSource.getLastSrTimestamp() ); + + rtcpPacket->body.rr.ssrcN = htonl(mRtspThread.getSsrc()); + rtcpPacket->body.rr.rr[0].ssrcN = htonl(mRtpSource.getSsrc()); + rtcpPacket->body.rr.rr[0].lost = mRtpSource.getLostPackets(); + rtcpPacket->body.rr.rr[0].fraction = mRtpSource.getLostFraction(); + rtcpPacket->body.rr.rr[0].lastSeqN = htonl(mRtpSource.getMaxSeq()); + rtcpPacket->body.rr.rr[0].jitterN = htonl(mRtpSource.getJitter()); + rtcpPacket->body.rr.rr[0].lsrN = htonl(mRtpSource.getLastSrTimestamp()); + rtcpPacket->body.rr.rr[0].dlsrN = 0; + + return( wordLen*sizeof(uint32_t) ); +} + +int RtpCtrlThread::generateSdes( const unsigned char *packet, ssize_t packetLen ) +{ + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + + const std::string &cname = mRtpSource.getCname(); + + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.sdes)+sizeof(rtcpPacket->body.sdes.item[0])+cname.size(); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_SDES; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); + + rtcpPacket->body.sdes.srcN = htonl(mRtpSource.getSsrc()); + rtcpPacket->body.sdes.item[0].type = RTCP_SDES_CNAME; + rtcpPacket->body.sdes.item[0].len = cname.size(); + memcpy( rtcpPacket->body.sdes.item[0].data, cname.data(), cname.size() ); + + return( wordLen*sizeof(uint32_t) ); +} + +int RtpCtrlThread::generateBye( const unsigned char *packet, ssize_t packetLen ) +{ + RtcpPacket *rtcpPacket = (RtcpPacket *)packet; + + int byteLen = sizeof(rtcpPacket->header)+sizeof(rtcpPacket->body.bye)+sizeof(rtcpPacket->body.bye.srcN[0]); + int wordLen = ((byteLen-1)/sizeof(uint32_t))+1; + + rtcpPacket->header.version = RTP_VERSION; + rtcpPacket->header.p = 0; + rtcpPacket->header.pt = RTCP_BYE; + rtcpPacket->header.count = 1; + rtcpPacket->header.lenN = htons(wordLen-1); + + rtcpPacket->body.bye.srcN[0] = htonl(mRtpSource.getSsrc()); + + return( wordLen*sizeof(uint32_t) ); +} + +int RtpCtrlThread::recvPackets( unsigned char *buffer, ssize_t nBytes ) +{ + unsigned char *bufferPtr = buffer; + + // u_int32 len; /* length of compound RTCP packet in words */ + // rtcp_t *r; /* RTCP header */ + // rtcp_t *end; /* end of compound RTCP packet */ + + // if ((*(u_int16 *)r & RTCP_VALID_MASK) != RTCP_VALID_VALUE) { + // /* something wrong with packet format */ + // } + // end = (rtcp_t *)((u_int32 *)r + len); + + // do r = (rtcp_t *)((u_int32 *)r + r->common.length + 1); + // while (r < end && r->common.version == 2); + + // if (r != end) { + // /* something wrong with packet format */ + // } + + while ( nBytes > 0 ) + { + int consumed = recvPacket( bufferPtr, nBytes ); + if ( consumed <= 0 ) + break; + bufferPtr += consumed; + nBytes -= consumed; + } + return( nBytes ); +} + +int RtpCtrlThread::run() +{ + Debug( 2, "Starting control thread %x on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalCtrlPort() ); + SockAddrInet localAddr, remoteAddr; + + bool sendReports; + UdpInetSocket rtpCtrlServer; + if ( mRtpSource.getLocalHost() != "" ) + { + localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort(), "udp" ); + if ( !rtpCtrlServer.bind( localAddr ) ) + Fatal( "Failed to bind RTCP server" ); + sendReports = false; + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); + } + else + { + localAddr.resolve( mRtpSource.getLocalCtrlPort(), "udp" ); + if ( !rtpCtrlServer.bind( localAddr ) ) + Fatal( "Failed to bind RTCP server" ); + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalCtrlPort() ); + remoteAddr.resolve( mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort(), "udp" ); + if ( !rtpCtrlServer.connect( remoteAddr ) ) + Fatal( "Failed to connect RTCP server" ); + Debug( 3, "Connected to %s:%d", mRtpSource.getRemoteHost().c_str(), mRtpSource.getRemoteCtrlPort() ); + sendReports = true; + } + + Select select( 10 ); + select.addReader( &rtpCtrlServer ); + + unsigned char buffer[ZM_NETWORK_BUFSIZ]; + while ( !mStop && select.wait() >= 0 ) + { + if ( mStop ) + break; + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) + { + Error( "RTCP timed out" ); + break; + } + for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) + { + if ( UdpInetSocket *socket = dynamic_cast(*iter) ) + { + ssize_t nBytes = socket->recv( buffer, sizeof(buffer) ); + Debug( 4, "Read %zd bytes on sd %d", nBytes, socket->getReadDesc() ); + + if ( nBytes ) + { + recvPackets( buffer, nBytes ); + + if ( sendReports ) + { + unsigned char *bufferPtr = buffer; + bufferPtr += generateRr( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + bufferPtr += generateSdes( bufferPtr, sizeof(buffer)-(bufferPtr-buffer) ); + Debug( 4, "Sending %zd bytes on sd %d", bufferPtr-buffer, rtpCtrlServer.getWriteDesc() ); + if ( (nBytes = rtpCtrlServer.send( buffer, bufferPtr-buffer )) < 0 ) + Error( "Unable to send: %s", strerror( errno ) ); + //Debug( 4, "Sent %d bytes on sd %d", nBytes, rtpCtrlServer.getWriteDesc() ); + } + } + else + { + mStop = true; + break; + } + } + else + { + Panic( "Barfed" ); + } + } + } + rtpCtrlServer.close(); + mRtspThread.stop(); + return( 0 ); +} + +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtp_ctrl.h b/src/zm_rtp_ctrl.h new file mode 100644 index 000000000..9b44b752b --- /dev/null +++ b/src/zm_rtp_ctrl.h @@ -0,0 +1,157 @@ +// +// ZoneMinder RTCP Class Interface, $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. +// + +#ifndef ZM_RTP_CTRL_H +#define ZM_RTP_CTRL_H + +#include "zm_rtp.h" +#include "zm_comms.h" +#include "zm_thread.h" + +// Defined in ffmpeg rtp.h +//#define RTP_MAX_SDES 255 // maximum text length for SDES + +// Big-endian mask for version, padding bit and packet type pair +#define RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe) +#define RTCP_VALID_VALUE ((RTP_VERSION << 14) | RTCP_SR) + +class RtspThread; +class RtpSource; + +class RtpCtrlThread : public Thread +{ +friend class RtspThread; + +private: + typedef enum + { + RTCP_SR = 200, + RTCP_RR = 201, + RTCP_SDES = 202, + RTCP_BYE = 203, + RTCP_APP = 204 + } RtcpType; + + typedef enum + { + RTCP_SDES_END = 0, + RTCP_SDES_CNAME = 1, + RTCP_SDES_NAME = 2, + RTCP_SDES_EMAIL = 3, + RTCP_SDES_PHONE = 4, + RTCP_SDES_LOC = 5, + RTCP_SDES_TOOL = 6, + RTCP_SDES_NOTE = 7, + RTCP_SDES_PRIV = 8 + } RtcpSdesType; + + struct RtcpCommonHeader + { + uint8_t count:5; // varies by packet type + uint8_t p:1; // padding flag + uint8_t version:2; // protocol version + uint8_t pt; // RTCP packet type + uint16_t lenN; // pkt len in words, w/o this word, network order + }; + + // Reception report block + struct RtcpRr + { + uint32_t ssrcN; // data source being reported + int32_t lost:24; // cumul. no. pkts lost (signed!) + uint32_t fraction:8; // fraction lost since last SR/RR + uint32_t lastSeqN; // extended last seq. no. received, network order + uint32_t jitterN; // interarrival jitter, network order + uint32_t lsrN; // last SR packet from this source, network order + uint32_t dlsrN; // delay since last SR packet, network order + }; + + // SDES item + struct RtcpSdesItem + { + uint8_t type; // type of item (rtcp_sdes_type_t) + uint8_t len; // length of item (in octets) + char data[]; // text, not null-terminated + }; + + // RTCP packet + struct RtcpPacket + { + RtcpCommonHeader header; // common header + union + { + // Sender Report (SR) + struct Sr + { + uint32_t ssrcN; // sender generating this report, network order + uint32_t ntpSecN; // NTP timestamp, network order + uint32_t ntpFracN; + uint32_t rtpTsN; // RTP timestamp, network order + uint32_t pSentN; // packets sent, network order + uint32_t oSentN; // octets sent, network order + RtcpRr rr[]; // variable-length list + } sr; + + // Reception Report (RR) + struct Rr + { + uint32_t ssrcN; // receiver generating this report + RtcpRr rr[]; // variable-length list + } rr; + + // source description (SDES) + struct Sdes + { + uint32_t srcN; // first SSRC/CSRC + RtcpSdesItem item[]; // list of SDES items + } sdes; + + // BYE + struct Bye + { + uint32_t srcN[]; // list of sources + // can't express trailing text for reason (what does this mean? it's not even english!) + } bye; + } body; + }; + +private: + RtspThread &mRtspThread; + RtpSource &mRtpSource; + int mPort; + bool mStop; + +private: + int recvPacket( const unsigned char *packet, ssize_t packetLen ); + int generateRr( const unsigned char *packet, ssize_t packetLen ); + int generateSdes( const unsigned char *packet, ssize_t packetLen ); + int generateBye( const unsigned char *packet, ssize_t packetLen ); + int recvPackets( unsigned char *buffer, ssize_t nBytes ); + int run(); + +public: + RtpCtrlThread( RtspThread &rtspThread, RtpSource &rtpSource ); + + void stop() + { + mStop = true; + } +}; + +#endif // ZM_RTP_CTRL_H diff --git a/src/zm_rtp_data.cpp b/src/zm_rtp_data.cpp new file mode 100644 index 000000000..257f46947 --- /dev/null +++ b/src/zm_rtp_data.cpp @@ -0,0 +1,120 @@ +// +// ZoneMinder RTP Data Class Implementation, $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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_rtp_data.h" + +#include "zm_rtsp.h" + +#include + +RtpDataThread::RtpDataThread( RtspThread &rtspThread, RtpSource &rtpSource ) : mRtspThread( rtspThread ), mRtpSource( rtpSource ), mStop( false ) +{ +} + +bool RtpDataThread::recvPacket( const unsigned char *packet, size_t packetLen ) +{ + const RtpDataHeader *rtpHeader; + rtpHeader = (RtpDataHeader *)packet; + + //printf( "D: " ); + //for ( int i = 0; i < 32; i++ ) + //printf( "%02x ", (unsigned char)packet[i] ); + //printf( "\n" ); + + Debug( 5, "Ver: %d", rtpHeader->version ); + Debug( 5, "P: %d", rtpHeader->p ); + Debug( 5, "Pt: %d", rtpHeader->pt ); + Debug( 5, "Mk: %d", rtpHeader->m ); + Debug( 5, "Seq: %d", ntohs(rtpHeader->seqN) ); + Debug( 5, "T/S: %x", ntohl(rtpHeader->timestampN) ); + Debug( 5, "SSRC: %x", ntohl(rtpHeader->ssrcN) ); + + //unsigned short seq = ntohs(rtpHeader->seqN); + unsigned long ssrc = ntohl(rtpHeader->ssrcN); + + if ( mRtpSource.getSsrc() && (ssrc != mRtpSource.getSsrc()) ) + { + Warning( "Discarding packet for unrecognised ssrc %lx", ssrc ); + return( false ); + } + + return( mRtpSource.handlePacket( packet, packetLen ) ); +} + +int RtpDataThread::run() +{ + Debug( 2, "Starting data thread %d on port %d", mRtpSource.getSsrc(), mRtpSource.getLocalDataPort() ); + + SockAddrInet localAddr; + UdpInetServer rtpDataSocket; + if ( mRtpSource.getLocalHost() != "" ) + localAddr.resolve( mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort(), "udp" ); + else + localAddr.resolve( mRtpSource.getLocalDataPort(), "udp" ); + if ( !rtpDataSocket.bind( localAddr ) ) + Fatal( "Failed to bind RTP server" ); + Debug( 3, "Bound to %s:%d", mRtpSource.getLocalHost().c_str(), mRtpSource.getLocalDataPort() ); + + Select select( 3 ); + select.addReader( &rtpDataSocket ); + + unsigned char buffer[ZM_NETWORK_BUFSIZ]; + while ( !mStop && select.wait() >= 0 ) + { + if ( mStop ) + break; + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) + { + Error( "RTP timed out" ); + mStop = true; + break; + } + for ( Select::CommsList::iterator iter = readable.begin(); iter != readable.end(); iter++ ) + { + if ( UdpInetServer *socket = dynamic_cast(*iter) ) + { + int nBytes = socket->recv( buffer, sizeof(buffer) ); + Debug( 4, "Got %d bytes on sd %d", nBytes, socket->getReadDesc() ); + if ( nBytes ) + { + recvPacket( buffer, nBytes ); + } + else + { + mStop = true; + break; + } + } + else + { + Panic( "Barfed" ); + } + } + } + rtpDataSocket.close(); + mRtspThread.stop(); + return( 0 ); +} + +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtp_data.h b/src/zm_rtp_data.h new file mode 100644 index 000000000..6c957a3ad --- /dev/null +++ b/src/zm_rtp_data.h @@ -0,0 +1,67 @@ +// +// ZoneMinder RTP Data Class Interface, $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. +// + +#ifndef ZM_RTP_DATA_H +#define ZM_RTP_DATA_H + +#include "zm_thread.h" +#include "zm_buffer.h" + +#include + +class RtspThread; +class RtpSource; + +struct RtpDataHeader +{ + uint8_t cc:4; // CSRC count + uint8_t x:1; // header extension flag + uint8_t p:1; // padding flag + uint8_t version:2; // protocol version + uint8_t pt:7; // payload type + uint8_t m:1; // marker bit + uint16_t seqN; // sequence number, network order + uint32_t timestampN; // timestamp, network order + uint32_t ssrcN; // synchronization source, network order + uint32_t csrc[]; // optional CSRC list +}; + +class RtpDataThread : public Thread +{ +friend class RtspThread; + +private: + RtspThread &mRtspThread; + RtpSource &mRtpSource; + bool mStop; + +private: + bool recvPacket( const unsigned char *packet, size_t packetLen ); + int run(); + +public: + RtpDataThread( RtspThread &rtspThread, RtpSource &rtpSource ); + + void stop() + { + mStop = true; + } +}; + +#endif // ZM_RTP_DATA_H diff --git a/src/zm_rtp_source.cpp b/src/zm_rtp_source.cpp new file mode 100644 index 000000000..4f53327df --- /dev/null +++ b/src/zm_rtp_source.cpp @@ -0,0 +1,325 @@ +// +// ZoneMinder RTP Source Class Implementation, $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. +// + +#include "zm_rtp_source.h" + +#include "zm_time.h" +#include "zm_rtp_data.h" + +#include + +RtpSource::RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime ) : + mId( id ), + mSsrc( ssrc ), + mLocalHost( localHost ), + mRemoteHost( remoteHost ), + mRtpClock( rtpClock ), + mFrame( 65536 ), + mFrameCount( 0 ), + mFrameGood( true ), + mFrameReady( false ), + mFrameProcessed( false ) +{ + char hostname[256] = ""; + gethostname( hostname, sizeof(hostname) ); + + mCname = stringtf( "zm-%d@%s", mId, hostname ); + Debug( 3, "RTP CName = %s", mCname.c_str() ); + + init( seq ); + mMaxSeq = seq - 1; + mProbation = MIN_SEQUENTIAL; + + mLocalPortChans[0] = localPortBase; + mLocalPortChans[1] = localPortBase+1; + + mRemotePortChans[0] = remotePortBase; + mRemotePortChans[1] = remotePortBase+1; + + mRtpFactor = mRtpClock; + + mBaseTimeReal = tvNow(); + mBaseTimeNtp = tvZero(); + mBaseTimeRtp = rtpTime; + + mLastSrTimeReal = tvZero(); + mLastSrTimeNtp = tvZero(); + mLastSrTimeRtp = 0; +} + +void RtpSource::init( uint16_t seq ) +{ + Debug( 3, "Initialising sequence" ); + mBaseSeq = seq; + mMaxSeq = seq; + mBadSeq = RTP_SEQ_MOD + 1; // so seq == mBadSeq is false + mCycles = 0; + mReceivedPackets = 0; + mReceivedPrior = 0; + mExpectedPrior = 0; + // other initialization + mJitter = 0; + mTransit = 0; +} + +bool RtpSource::updateSeq( uint16_t seq ) +{ + uint16_t uDelta = seq - mMaxSeq; + + // Source is not valid until MIN_SEQUENTIAL packets with + // sequential sequence numbers have been received. + Debug( 5, "Seq: %d", seq ); + + if ( mProbation) + { + // packet is in sequence + if ( seq == mMaxSeq + 1) + { + Debug( 3, "Sequence in probation %d, in sequence", mProbation ); + mProbation--; + mMaxSeq = seq; + if ( mProbation == 0 ) + { + init( seq ); + mReceivedPackets++; + return( true ); + } + } + else + { + Warning( "Sequence in probation %d, out of sequence", mProbation ); + mProbation = MIN_SEQUENTIAL - 1; + mMaxSeq = seq; + return( false ); + } + return( true ); + } + else if ( uDelta < MAX_DROPOUT ) + { + if ( uDelta == 1 ) + { + Debug( 3, "Packet in sequence, gap %d", uDelta ); + } + else + { + Warning( "Packet in sequence, gap %d", uDelta ); + } + + // in order, with permissible gap + if ( seq < mMaxSeq ) + { + // Sequence number wrapped - count another 64K cycle. + mCycles += RTP_SEQ_MOD; + } + mMaxSeq = seq; + } + else if ( uDelta <= RTP_SEQ_MOD - MAX_MISORDER ) + { + Warning( "Packet out of sequence, gap %d", uDelta ); + // the sequence number made a very large jump + if ( seq == mBadSeq ) + { + Debug( 3, "Restarting sequence" ); + // Two sequential packets -- assume that the other side + // restarted without telling us so just re-sync + // (i.e., pretend this was the first packet). + init( seq ); + } + else + { + mBadSeq = (seq + 1) & (RTP_SEQ_MOD-1); + return( false ); + } + } + else + { + Warning( "Packet duplicate or reordered, gap %d", uDelta ); + // duplicate or reordered packet + return( false ); + } + mReceivedPackets++; + return( uDelta==1?true:false ); +} + +void RtpSource::updateJitter( const RtpDataHeader *header ) +{ + if ( mRtpFactor > 0 ) + { + Debug( 5, "Delta rtp = %.6f", tvDiffSec( mBaseTimeReal ) ); + uint32_t localTimeRtp = mBaseTimeRtp + uint32_t( tvDiffSec( mBaseTimeReal ) * mRtpFactor ); + Debug( 5, "Local RTP time = %x", localTimeRtp ); + Debug( 5, "Packet RTP time = %x", ntohl(header->timestampN) ); + uint32_t packetTransit = localTimeRtp - ntohl(header->timestampN); + Debug( 5, "Packet transit RTP time = %x", packetTransit ); + + if ( mTransit > 0 ) + { + // Jitter + int d = packetTransit - mTransit; + Debug( 5, "Jitter D = %d", d ); + if ( d < 0 ) + d = -d; + //mJitter += (1./16.) * ((double)d - mJitter); + mJitter += d - ((mJitter + 8) >> 4); + } + mTransit = packetTransit; + } + else + { + mJitter = 0; + } + Debug( 5, "RTP Jitter: %d", mJitter ); +} + +void RtpSource::updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ) +{ + struct timeval ntpTime = tvMake( ntpTimeSecs, suseconds_t((USEC_PER_SEC*(ntpTimeFrac>>16))/(1<<16)) ); + + Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); + + if ( mBaseTimeNtp.tv_sec == 0 ) + { + mBaseTimeReal = tvNow(); + mBaseTimeNtp = ntpTime; + mBaseTimeRtp = rtpTime; + } + else if ( !mRtpClock ) + { + Debug( 5, "lastSrNtpTime: %ld.%06ld, rtpTime: %x", mLastSrTimeNtp.tv_sec, mLastSrTimeNtp.tv_usec, rtpTime ); + Debug( 5, "ntpTime: %ld.%06ld, rtpTime: %x", ntpTime.tv_sec, ntpTime.tv_usec, rtpTime ); + + double diffNtpTime = tvDiffSec( mBaseTimeNtp, ntpTime ); + uint32_t diffRtpTime = rtpTime - mBaseTimeRtp; + + //Debug( 5, "Real-diff: %.6f", diffRealTime ); + Debug( 5, "NTP-diff: %.6f", diffNtpTime ); + Debug( 5, "RTP-diff: %d", diffRtpTime ); + + mRtpFactor = (uint32_t)(diffRtpTime / diffNtpTime); + + Debug( 5, "RTPfactor: %d", mRtpFactor ); + } + mLastSrTimeNtpSecs = ntpTimeSecs; + mLastSrTimeNtpFrac = ntpTimeFrac; + mLastSrTimeNtp = ntpTime; + mLastSrTimeRtp = rtpTime; +} + +void RtpSource::updateRtcpStats() +{ + uint32_t extendedMax = mCycles + mMaxSeq; + mExpectedPackets = extendedMax - mBaseSeq + 1; + + Debug( 5, "Expected packets = %d", mExpectedPackets ); + + // The number of packets lost is defined to be the number of packets + // expected less the number of packets actually received: + mLostPackets = mExpectedPackets - mReceivedPackets; + Debug( 5, "Lost packets = %d", mLostPackets ); + + uint32_t expectedInterval = mExpectedPackets - mExpectedPrior; + Debug( 5, "Expected interval = %d", expectedInterval ); + mExpectedPrior = mExpectedPackets; + uint32_t receivedInterval = mReceivedPackets - mReceivedPrior; + Debug( 5, "Received interval = %d", receivedInterval ); + mReceivedPrior = mReceivedPackets; + uint32_t lostInterval = expectedInterval - receivedInterval; + Debug( 5, "Lost interval = %d", lostInterval ); + + if ( expectedInterval == 0 || lostInterval <= 0 ) + mLostFraction = 0; + else + mLostFraction = (lostInterval << 8) / expectedInterval; + Debug( 5, "Lost fraction = %d", mLostFraction ); +} + +bool RtpSource::handlePacket( const unsigned char *packet, size_t packetLen ) +{ + const RtpDataHeader *rtpHeader; + rtpHeader = (RtpDataHeader *)packet; + + if ( updateSeq( ntohs(rtpHeader->seqN) ) ) + { + Hexdump( 4, packet+sizeof(RtpDataHeader), 16 ); + if ( mFrameGood ) + mFrame.append( packet+sizeof(RtpDataHeader), packetLen-sizeof(RtpDataHeader) ); + Hexdump( 4, mFrame.head(), 16 ); + + if ( rtpHeader->m ) + { + if ( mFrameGood ) + { + Debug( 2, "Got new frame %d, %d bytes", mFrameCount, mFrame.size() ); + + mFrameProcessed.setValueImmediate( false ); + mFrameReady.updateValueSignal( true ); + if ( !mFrameProcessed.getValueImmediate() ) + { + for ( int count = 0; !mFrameProcessed.getUpdatedValue( 1 ); count++ ) + if( count > 1 ) + return( false ); + } + mFrameCount++; + } + else + { + Warning( "Discarding incomplete frame %d, %d bytes", mFrameCount, mFrame.size() ); + } + mFrame.clear(); + } + } + else + { + if ( mFrame.size() ) + { + Warning( "Discarding partial frame %d, %d bytes", mFrameCount, mFrame.size() ); + } + else + { + Warning( "Discarding frame %d", mFrameCount ); + } + mFrameGood = false; + mFrame.clear(); + } + if ( rtpHeader->m ) + { + mFrameGood = true; + } + + updateJitter( rtpHeader ); + + return( true ); +} + +bool RtpSource::getFrame( Buffer &buffer ) +{ + Debug( 3, "Getting frame" ); + if ( !mFrameReady.getValueImmediate() ) + { + // Allow for a couple of spurious returns + for ( int count = 0; !mFrameReady.getUpdatedValue( 1 ); count++ ) + if ( count > 1 ) + return( false ); + } + buffer = mFrame; + mFrameReady.setValueImmediate( false ); + mFrameProcessed.updateValueSignal( true ); + Debug( 3, "Copied %d bytes", buffer.size() ); + return( true ); +} diff --git a/src/zm_rtp_source.h b/src/zm_rtp_source.h new file mode 100644 index 000000000..7d4143697 --- /dev/null +++ b/src/zm_rtp_source.h @@ -0,0 +1,179 @@ +// +// ZoneMinder RTP Source Class Interface, $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. +// + +#ifndef ZM_RTP_SOURCE_H +#define ZM_RTP_SOURCE_H + +#include "zm_buffer.h" +#include "zm_thread.h" + +#include +#include +#include + +struct RtpDataHeader; + +class RtpSource +{ +public: + typedef enum { EMPTY, FILLING, READY } FrameState; +private: + static const int RTP_SEQ_MOD = 1<<16; + static const int MAX_DROPOUT = 3000; + static const int MAX_MISORDER = 100; + static const int MIN_SEQUENTIAL = 2; + +private: + // Identity + int mId; // General id (usually monitor id) + std::string mCname; // Canonical name, for SDES + + // RTP/RTCP fields + uint32_t mSsrc; + uint16_t mMaxSeq; // highest seq. number seen + uint32_t mCycles; // shifted count of seq. number cycles + uint32_t mBaseSeq; // base seq number + uint32_t mBadSeq; // last 'bad' seq number + 1 + uint32_t mProbation; // sequ. packets till source is valid + uint32_t mReceivedPackets; // packets received + uint32_t mExpectedPrior; // packet expected at last interval + uint32_t mReceivedPrior; // packet received at last interval + uint32_t mTransit; // relative trans time for prev pkt + uint32_t mJitter; // estimated jitter + + // Ports/Channels + std::string mLocalHost; + int mLocalPortChans[2]; + std::string mRemoteHost; + int mRemotePortChans[2]; + + // Time keys + uint32_t mRtpClock; + uint32_t mRtpFactor; + struct timeval mBaseTimeReal; + struct timeval mBaseTimeNtp; + uint32_t mBaseTimeRtp; + + struct timeval mLastSrTimeReal; + uint32_t mLastSrTimeNtpSecs; + uint32_t mLastSrTimeNtpFrac; + struct timeval mLastSrTimeNtp; + uint32_t mLastSrTimeRtp; + + // Stats, intermittently updated + uint32_t mExpectedPackets; + uint32_t mLostPackets; + uint8_t mLostFraction; + + Buffer mFrame; + int mFrameCount; + bool mFrameGood; + ThreadData mFrameReady; + ThreadData mFrameProcessed; + +private: + void init( uint16_t seq ); + +public: + RtpSource( int id, const std::string &localHost, int localPortBase, const std::string &remoteHost, int remotePortBase, uint32_t ssrc, uint16_t seq, uint32_t rtpClock, uint32_t rtpTime ); + bool updateSeq( uint16_t seq ); + void updateJitter( const RtpDataHeader *header ); + void updateRtcpData( uint32_t ntpTimeSecs, uint32_t ntpTimeFrac, uint32_t rtpTime ); + void updateRtcpStats(); + + bool handlePacket( const unsigned char *packet, size_t packetLen ); + + uint32_t getSsrc() const + { + return( mSsrc ); + } + void setSsrc( uint32_t ssrc ) + { + mSsrc = ssrc; + } + + bool getFrame( Buffer &buffer ); + + const std::string &getCname() const + { + return( mCname ); + } + + const std::string &getLocalHost() const + { + return( mLocalHost ); + } + + int getLocalDataPort() const + { + return( mLocalPortChans[0] ); + } + + int getLocalCtrlPort() const + { + return( mLocalPortChans[1] ); + } + + const std::string &getRemoteHost() const + { + return( mRemoteHost ); + } + + int getRemoteDataPort() const + { + return( mRemotePortChans[0] ); + } + + int getRemoteCtrlPort() const + { + return( mRemotePortChans[1] ); + } + + uint32_t getMaxSeq() const + { + return( mCycles + mMaxSeq ); + } + + uint32_t getExpectedPackets() const + { + return( mExpectedPackets ); + } + + uint32_t getLostPackets() const + { + return( mLostPackets ); + } + + uint8_t getLostFraction() const + { + return( mLostFraction ); + } + + uint32_t getJitter() const + { + return( mJitter >> 4 ); + } + + uint32_t getLastSrTimestamp() const + { + return( ((mLastSrTimeNtpSecs&0xffff)<<16)|(mLastSrTimeNtpFrac>>16) ); + } +}; + +#endif // ZM_RTP_SOURCE_H diff --git a/src/zm_rtsp.cpp b/src/zm_rtsp.cpp new file mode 100644 index 000000000..a86c8bbb0 --- /dev/null +++ b/src/zm_rtsp.cpp @@ -0,0 +1,719 @@ +// +// ZoneMinder RTSP Class Implementation, $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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_rtsp.h" + +#include "zm_rtp_data.h" +#include "zm_rtp_ctrl.h" +#include "zm_db.h" +#include "zm_sdp.h" + +#include +#include +#include +#include + +int RtspThread::smMinDataPort = 0; +int RtspThread::smMaxDataPort = 0; +RtspThread::PortSet RtspThread::smAssignedPorts; + +bool RtspThread::sendCommand( std::string message ) +{ + if ( !mAuth.empty() ) + message += stringtf( "Authorization: Basic %s\r\n", mAuth64.c_str() ); + message += stringtf( "User-Agent: ZoneMinder/%s\r\n", ZM_VERSION ); + message += stringtf( "CSeq: %d\r\n\r\n", ++mSeq ); + Debug( 2, "Sending RTSP message: %s", message.c_str() ); + if ( mMethod == RTP_RTSP_HTTP ) + { + message = base64Encode( message ); + Debug( 2, "Sending encoded RTSP message: %s", message.c_str() ); + if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( false ); + } + } + else + { + if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( false ); + } + } + return( true ); +} + +bool RtspThread::recvResponse( std::string &response ) +{ + if ( mRtspSocket.recv( response ) < 0 ) + Error( "Recv failed; %s", strerror(errno) ); + Debug( 2, "Received RTSP response: %s (%zd bytes)", response.c_str(), response.size() ); + float respVer = 0; + int respCode = -1; + char respText[ZM_NETWORK_BUFSIZ]; + if ( sscanf( response.c_str(), "RTSP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) + { + if ( isalnum(response[0]) ) + { + Error( "Response parse failure in '%s'", response.c_str() ); + } + else + { + Error( "Response parse failure, %zd bytes follow", response.size() ); + if ( response.size() ) + Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); + } + return( false ); + } + if ( respCode != 200 ) + { + Error( "Unexpected response code %d, text is '%s'", respCode, respText ); + return( false ); + } + return( true ); +} + +int RtspThread::requestPorts() +{ + if ( !smMinDataPort ) + { + char sql[ZM_SQL_SML_BUFSIZ]; + strncpy( sql, "select Id from Monitors where Function != 'None' and Type = 'Remote' and Protocol = 'rtsp' and Method = 'rtpUni' order by Id asc", sizeof(sql) ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int nMonitors = mysql_num_rows( result ); + int position = 0; + if ( nMonitors ) + { + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int id = atoi(dbrow[0]); + if ( mId == id ) + { + position = i; + break; + } + } + } + else + { + // Minor hack for testing when not strictly enabled + nMonitors = 1; + position = 0; + } + int portRange = int(((config.max_rtp_port-config.min_rtp_port)+1)/nMonitors); + smMinDataPort = config.min_rtp_port + (position * portRange); + smMaxDataPort = smMinDataPort + portRange - 1; + Debug( 2, "Assigned RTP port range is %d-%d", smMinDataPort, smMaxDataPort ); + } + for ( int i = smMinDataPort; i <= smMaxDataPort; i++ ) + { + PortSet::const_iterator iter = smAssignedPorts.find( i ); + if ( iter == smAssignedPorts.end() ) + { + smAssignedPorts.insert( i ); + return( i ); + } + } + Panic( "Can assign RTP port, no ports left in pool" ); + return( -1 ); +} + +void RtspThread::releasePorts( int port ) +{ + if ( port > 0 ) + smAssignedPorts.erase( port ); +} + +RtspThread::RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth ) : + mId( id ), + mMethod( method ), + mProtocol( protocol ), + mHost( host ), + mPort( port ), + mPath( path ), + mAuth( auth ), + mFormatContext( 0 ), + mSeq( 0 ), + mSession( 0 ), + mSsrc( 0 ), + mDist( UNDEFINED ), + mRtpTime( 0 ), + mStop( false ) +{ + mUrl = mProtocol+"://"+mHost+":"+mPort; + if ( !mPath.empty() ) + { + if ( mPath[0] == '/' ) + mUrl += mPath; + else + mUrl += '/'+mPath; + } + + mSsrc = rand(); + + Debug( 2, "RTSP Local SSRC is %x", mSsrc ); + + if ( mMethod == RTP_RTSP_HTTP ) + mHttpSession = stringtf( "%d", rand() ); + + if ( !mAuth.empty() ) + mAuth64 = base64Encode( mAuth ); +} + +RtspThread::~RtspThread() +{ +} + +int RtspThread::run() +{ + std::string message; + std::string response; + + response.reserve( ZM_NETWORK_BUFSIZ ); + + if ( !mRtspSocket.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) + Fatal( "Unable to connect RTSP socket" ); + //Select select( 0.25 ); + //select.addReader( &mRtspSocket ); + //while ( select.wait() ) + //{ + //mRtspSocket.recv( response ); + //Debug( 4, "Drained %d bytes from RTSP socket", response.size() ); + //} + + if ( mMethod == RTP_RTSP_HTTP ) + { + if ( !mRtspSocket2.connect( mHost.c_str(), strtol( mPort.c_str(), NULL, 10 ) ) ) + Fatal( "Unable to connect auxiliary RTSP/HTTP socket" ); + //Select select( 0.25 ); + //select.addReader( &mRtspSocket2 ); + //while ( select.wait() ) + //{ + //mRtspSocket2.recv( response ); + //Debug( 4, "Drained %d bytes from HTTP socket", response.size() ); + //} + + message = "GET "+mPath+" HTTP/1.0\r\n"; + message += "X-SessionCookie: "+mHttpSession+"\r\n"; + if ( !mAuth.empty() ) + message += stringtf( "Authorization: Basic %s\r\n", mAuth64.c_str() ); + message += "\r\n"; + Debug( 2, "Sending HTTP message: %s", message.c_str() ); + if ( mRtspSocket.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( -1 ); + } + if ( mRtspSocket.recv( response ) < 0 ) + { + Error( "Recv failed; %s", strerror(errno) ); + return( -1 ); + } + + Debug( 2, "Received HTTP response: %s (%zd bytes)", response.c_str(), response.size() ); + float respVer = 0; + int respCode = -1; + char respText[256]; + if ( sscanf( response.c_str(), "HTTP/%f %3d %[^\r\n]\r\n", &respVer, &respCode, respText ) != 3 ) + { + if ( isalnum(response[0]) ) + { + Error( "Response parse failure in '%s'", response.c_str() ); + } + else + { + Error( "Response parse failure, %zd bytes follow", response.size() ); + if ( response.size() ) + Hexdump( Logger::ERROR, response.data(), min(response.size(),16) ); + } + return( -1 ); + } + if ( respCode != 200 ) + { + Error( "Unexpected response code %d, text is '%s'", respCode, respText ); + return( -1 ); + } + + message = "POST "+mPath+" HTTP/1.0\r\n"; + message += "X-SessionCookie: "+mHttpSession+"\r\n"; + if ( !mAuth.empty() ) + message += stringtf( "Authorization: Basic %s\r\n", mAuth64.c_str() ); + message += "Content-Length: 32767\r\n"; + message += "Content-Type: application/x-rtsp-tunnelled\r\n"; + message += "\r\n"; + Debug( 2, "Sending HTTP message: %s", message.c_str() ); + if ( mRtspSocket2.send( message.c_str(), message.size() ) != (int)message.length() ) + { + Error( "Unable to send message '%s': %s", message.c_str(), strerror(errno) ); + return( -1 ); + } + } + + std::string localHost = ""; + int localPorts[2] = { 0, 0 }; + + //message = "OPTIONS * RTSP/1.0\r\n"; + //sendCommand( message ); + //recvResponse( response ); + + message = "DESCRIBE "+mUrl+" RTSP/1.0\r\n"; + sendCommand( message ); + sleep( 1 ); + recvResponse( response ); + + const std::string endOfHeaders = "\r\n\r\n"; + size_t sdpStart = response.find( endOfHeaders ); + if( sdpStart == std::string::npos ) + return( -1 ); + sdpStart += endOfHeaders.length(); + + std::string sdp = response.substr( sdpStart ); + Debug( 1, "Processing SDP '%s'", sdp.c_str() ); + + SessionDescriptor *sessDesc = 0; + try + { + sessDesc = new SessionDescriptor( mUrl, sdp ); + mFormatContext = sessDesc->generateFormatContext(); + } + catch( const Exception &e ) + { + Error( e.getMessage().c_str() ); + return( -1 ); + } + +#if 0 + // New method using ffmpeg native functions + std::string authUrl = mUrl; + if ( !mAuth.empty() ) + authUrl.insert( authUrl.find( "://" )+3, mAuth+"@" ); + + if ( av_open_input_file( &mFormatContext, authUrl.c_str(), NULL, 0, NULL ) != 0 ) + { + Error( "Unable to open input '%s'", authUrl.c_str() ); + return( -1 ); + } +#endif + + uint32_t rtpClock = 0; + std::string trackUrl = mUrl; + if ( mFormatContext->nb_streams >= 1 ) + { + for ( unsigned int i = 0; i < mFormatContext->nb_streams; i++ ) + { + SessionDescriptor::MediaDescriptor *mediaDesc = sessDesc->getStream( i ); +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + if ( mFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO ) +#else + if ( mFormatContext->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO ) +#endif + { + trackUrl += "/"+mediaDesc->getControlUrl(); + rtpClock = mediaDesc->getClock(); + // Hackery pokery + //rtpClock = mFormatContext->streams[i]->codec->sample_rate; + break; + } + } + } + + switch( mMethod ) + { + case RTP_UNICAST : + { + localPorts[0] = requestPorts(); + localPorts[1] = localPorts[0]+1; + + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;unicast;client_port="+stringtf( "%d", localPorts[0] )+"-"+stringtf( "%d", localPorts[1] )+"\r\n"; + break; + } + case RTP_MULTICAST : + { + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP;multicast\r\n"; + break; + } + case RTP_RTSP : + case RTP_RTSP_HTTP : + { + message = "SETUP "+trackUrl+" RTSP/1.0\r\nTransport: RTP/AVP/TCP;unicast\r\n"; + break; + } + default: + { + Panic( "Got unexpected method %d", mMethod ); + break; + } + } + + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + StringVector lines = split( response, "\r\n" ); + char *session = 0; + int timeout = 0; + char transport[256] = ""; + + for ( size_t i = 0; i < lines.size(); i++ ) + { + sscanf( lines[i].c_str(), "Session: %a[0-9a-fA-F]; timeout=%d", &session, &timeout ); + sscanf( lines[i].c_str(), "Transport: %s", transport ); + } + + if ( !session ) + Fatal( "Unable to get session identifier from response '%s'", response.c_str() ); + + Debug( 2, "Got RTSP session %s, timeout %d secs", session, timeout ); + + if ( !transport[0] ) + Fatal( "Unable to get transport details from response '%s'", response.c_str() ); + + Debug( 2, "Got RTSP transport %s", transport ); + + std::string method = ""; + int remotePorts[2] = { 0, 0 }; + int remoteChannels[2] = { 0, 0 }; + std::string distribution = ""; + unsigned long ssrc = 0; + StringVector parts = split( transport, ";" ); + for ( size_t i = 0; i < parts.size(); i++ ) + { + if ( parts[i] == "unicast" || parts[i] == "multicast" ) + distribution = parts[i]; + else if ( startsWith( parts[i], "server_port=" ) ) + { + method = "RTP/UNICAST"; + StringVector subparts = split( parts[i], "=" ); + StringVector ports = split( subparts[1], "-" ); + remotePorts[0] = strtol( ports[0].c_str(), NULL, 10 ); + remotePorts[1] = strtol( ports[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "interleaved=" ) ) + { + method = "RTP/RTSP"; + StringVector subparts = split( parts[i], "=" ); + StringVector channels = split( subparts[1], "-" ); + remoteChannels[0] = strtol( channels[0].c_str(), NULL, 10 ); + remoteChannels[1] = strtol( channels[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "port=" ) ) + { + method = "RTP/MULTICAST"; + StringVector subparts = split( parts[i], "=" ); + StringVector ports = split( subparts[1], "-" ); + localPorts[0] = strtol( ports[0].c_str(), NULL, 10 ); + localPorts[1] = strtol( ports[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "destination=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + localHost = subparts[1]; + } + else if ( startsWith( parts[i], "ssrc=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + ssrc = strtoll( subparts[1].c_str(), NULL, 16 ); + } + } + + Debug( 2, "RTSP Method is %s", method.c_str() ); + Debug( 2, "RTSP Distribution is %s", distribution.c_str() ); + Debug( 2, "RTSP SSRC is %lx", ssrc ); + Debug( 2, "RTSP Local Host is %s", localHost.c_str() ); + Debug( 2, "RTSP Local Ports are %d/%d", localPorts[0], localPorts[1] ); + Debug( 2, "RTSP Remote Ports are %d/%d", remotePorts[0], remotePorts[1] ); + Debug( 2, "RTSP Remote Channels are %d/%d", remoteChannels[0], remoteChannels[1] ); + + message = "PLAY "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\nRange: npt=0.000-\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + lines = split( response, "\r\n" ); + char *rtpInfo = 0; + for ( size_t i = 0; i < lines.size(); i++ ) + { + sscanf( lines[i].c_str(), "RTP-Info: %as", &rtpInfo ); + } + + if ( !rtpInfo ) + Fatal( "Unable to get RTP Info identifier from response '%s'", response.c_str() ); + + Debug( 2, "Got RTP Info %s", rtpInfo ); + + int seq = 0; + unsigned long rtpTime = 0; + parts = split( rtpInfo, ";" ); + for ( size_t i = 0; i < parts.size(); i++ ) + { + if ( startsWith( parts[i], "seq=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + seq = strtol( subparts[1].c_str(), NULL, 10 ); + } + else if ( startsWith( parts[i], "rtptime=" ) ) + { + StringVector subparts = split( parts[i], "=" ); + rtpTime = strtol( subparts[1].c_str(), NULL, 10 ); + } + } + + Debug( 2, "RTSP Seq is %d", seq ); + Debug( 2, "RTSP Rtptime is %ld", rtpTime ); + + switch( mMethod ) + { + case RTP_UNICAST : + { + RtpSource *source = new RtpSource( mId, "", localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime ); + mSources[ssrc] = source; + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); + + rtpDataThread.start(); + rtpCtrlThread.start(); + + while( !mStop ) + { + usleep( 100000 ); + } +#if 0 + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); +#endif + + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + rtpDataThread.stop(); + rtpCtrlThread.stop(); + + //rtpDataThread.kill( SIGTERM ); + //rtpCtrlThread.kill( SIGTERM ); + + rtpDataThread.join(); + rtpCtrlThread.join(); + + delete mSources[ssrc]; + mSources.clear(); + + releasePorts( localPorts[0] ); + + break; + } + case RTP_RTSP : + case RTP_RTSP_HTTP : + { + RtpSource *source = new RtpSource( mId, "", remoteChannels[0], mHost, remoteChannels[0], ssrc, seq, rtpClock, rtpTime ); + mSources[ssrc] = source; + // These never actually run + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); + + Select select( double(config.http_timeout)/1000.0 ); + select.addReader( &mRtspSocket ); + + Buffer buffer( ZM_NETWORK_BUFSIZ ); + time_t lastKeepalive = time(NULL); + std::string keepaliveMessage = "OPTIONS * RTSP/1.0\r\n"; + std::string keepaliveResponse = "RTSP/1.0 200 OK\r\n"; + while ( !mStop && select.wait() >= 0 ) + { + Select::CommsList readable = select.getReadable(); + if ( readable.size() == 0 ) + { + Error( "RTSP timed out" ); + break; + } + + static char tempBuffer[ZM_NETWORK_BUFSIZ]; + ssize_t nBytes = mRtspSocket.recv( tempBuffer, sizeof(tempBuffer) ); + buffer.append( tempBuffer, nBytes ); + Debug( 4, "Read %zd bytes on sd %d, %d total", nBytes, mRtspSocket.getReadDesc(), buffer.size() ); + + while( buffer.size() > 0 ) + { + if ( buffer[0] == '$' ) + { + unsigned char channel = buffer[1]; + unsigned short len = ntohs( *((unsigned short *)(buffer+2)) ); + + Debug( 4, "Got %d bytes left, expecting %d byte packet on channel %d", buffer.size(), len, channel ); + if ( (unsigned short)buffer.size() < (len+4) ) + { + Debug( 4, "Missing %zd bytes, rereading", (len+4)-nBytes ); + break; + } + if ( channel == remoteChannels[0] ) + { + Debug( 4, "Got %d bytes on data channel %d, packet length is %d", buffer.size(), channel, len ); + Hexdump( 4, (char *)buffer, 16 ); + rtpDataThread.recvPacket( buffer+4, len ); + Debug( 4, "Received" ); + } + else if ( channel == remoteChannels[1] ) + { + len = ntohs( *((unsigned short *)(buffer+2)) ); + Debug( 4, "Got %zd bytes on control channel %d", nBytes, channel ); + rtpCtrlThread.recvPackets( buffer+4, len ); + } + else + { + Error( "Unexpected channel selector %d in RTSP interleaved data", buffer[1] ); + buffer.clear(); + break; + } + buffer.consume( len+4 ); + nBytes -= len+4; + } + else + { + if ( keepaliveResponse.compare( 0, keepaliveResponse.size(), (char *)buffer, keepaliveResponse.size() ) == 0 ) + { + Debug( 4, "Got keepalive response '%s'", (char *)buffer ); + //buffer.consume( keepaliveResponse.size() ); + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) + { + int discardBytes = charPtr-(char *)buffer; + buffer -= discardBytes; + } + else + { + buffer.clear(); + } + } + else + { + if ( char *charPtr = (char *)memchr( (char *)buffer, '$', buffer.size() ) ) + { + int discardBytes = charPtr-(char *)buffer; + Warning( "Unexpected format RTSP interleaved data, resyncing by %d bytes", discardBytes ); + Hexdump( -1, (char *)buffer, discardBytes ); + buffer -= discardBytes; + } + else + { + Warning( "Unexpected format RTSP interleaved data, dumping %d bytes", buffer.size() ); + Hexdump( -1, (char *)buffer, 32 ); + buffer.clear(); + } + } + } + } + if ( (timeout > 0) && ((time(NULL)-lastKeepalive) > (timeout-5)) ) + { + if ( !sendCommand( message ) ) + return( -1 ); + lastKeepalive = time(NULL); + } + buffer.tidy( 1 ); + } +#if 0 + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); +#endif + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + delete mSources[ssrc]; + mSources.clear(); + + break; + } + case RTP_MULTICAST : + { + RtpSource *source = new RtpSource( mId, localHost, localPorts[0], mHost, remotePorts[0], ssrc, seq, rtpClock, rtpTime ); + mSources[ssrc] = source; + RtpDataThread rtpDataThread( *this, *source ); + RtpCtrlThread rtpCtrlThread( *this, *source ); + + rtpDataThread.start(); + rtpCtrlThread.start(); + + while( !mStop ) + { + usleep( 100000 ); + } +#if 0 + message = "PAUSE "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); +#endif + message = "TEARDOWN "+mUrl+" RTSP/1.0\r\nSession: "+session+"\r\n"; + if ( !sendCommand( message ) ) + return( -1 ); + if ( !recvResponse( response ) ) + return( -1 ); + + rtpDataThread.stop(); + rtpCtrlThread.stop(); + + rtpDataThread.join(); + rtpCtrlThread.join(); + + delete mSources[ssrc]; + mSources.clear(); + + releasePorts( localPorts[0] ); + break; + } + default: + { + Panic( "Got unexpected method %d", mMethod ); + break; + } + } + + return( 0 ); +} + +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_rtsp.h b/src/zm_rtsp.h new file mode 100644 index 000000000..3f4621fa3 --- /dev/null +++ b/src/zm_rtsp.h @@ -0,0 +1,129 @@ +// +// ZoneMinder RTSP Class Interface, $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. +// + +#ifndef ZM_RTSP_H +#define ZM_RTSP_H + +#include "zm.h" +#include "zm_ffmpeg.h" +#include "zm_comms.h" +#include "zm_thread.h" +#include "zm_rtp_source.h" + +#include +#include + +class RtspThread : public Thread +{ +public: + typedef enum { RTP_UNICAST, RTP_MULTICAST, RTP_RTSP, RTP_RTSP_HTTP } RtspMethod; + typedef enum { UNDEFINED, UNICAST, MULTICAST } RtspDist; + +private: + typedef std::set PortSet; + typedef std::set SsrcSet; + typedef std::map SourceMap; + +private: + static int smMinDataPort; + static int smMaxDataPort; + static PortSet smLocalSsrcs; + static PortSet smAssignedPorts; + +private: + int mId; + RtspMethod mMethod; + std::string mProtocol; + std::string mHost; + std::string mPort; + std::string mPath; + std::string mUrl; + std::string mAuth; + std::string mAuth64; + + std::string mHttpSession; ///< Only for RTSP over HTTP sessions + + TcpInetClient mRtspSocket; + TcpInetClient mRtspSocket2; + + SourceMap mSources; + + AVFormatContext *mFormatContext; + + uint16_t mSeq; + uint32_t mSession; + uint32_t mSsrc; + + int mRemotePorts[2]; + int mRemoteChannels[2]; + RtspDist mDist; + + unsigned long mRtpTime; + + bool mStop; + +private: + bool sendCommand( std::string message ); + bool recvResponse( std::string &response ); + +public: + RtspThread( int id, RtspMethod method, const std::string &protocol, const std::string &host, const std::string &port, const std::string &path, const std::string &auth ); + ~RtspThread(); + +public: + int requestPorts(); + void releasePorts( int port ); + + bool isValidSsrc( uint32_t ssrc ); + bool updateSsrc( uint32_t ssrc, const RtpDataHeader *header ); + + uint32_t getSsrc() const + { + return( mSsrc ); + } + + bool hasSources() const + { + return( !mSources.empty() ); + } + + AVFormatContext *getFormatContext() + { + return( mFormatContext ); + } + + bool getFrame( Buffer &frame ) + { + SourceMap::iterator iter = mSources.begin(); + if ( iter == mSources.end() ) + return( false ); + return( iter->second->getFrame( frame ) ); + } + int run(); + void stop() + { + mStop = true; + } + bool stopped() const + { + return( mStop ); + } +}; + +#endif // ZM_RTSP_H diff --git a/src/zm_sdp.cpp b/src/zm_sdp.cpp new file mode 100644 index 000000000..aa33206c5 --- /dev/null +++ b/src/zm_sdp.cpp @@ -0,0 +1,403 @@ +// +// ZoneMinder SDP Class Implementation, $Date: 2009-04-14 21:20:02 +0100 (Tue, 14 Apr 2009) $, $Revision: 2850 $ +// 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. +// + +#include "zm.h" + +#if HAVE_LIBAVFORMAT + +#include "zm_sdp.h" + +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) +SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { + { 0, "PCMU", AVMEDIA_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8000, 1 }, + { 3, "GSM", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 4, "G723", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 5, "DVI4", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 6, "DVI4", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1 }, + { 7, "LPC", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 8, "PCMA", AVMEDIA_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1 }, + { 9, "G722", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 10, "L16", AVMEDIA_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2 }, + { 11, "L16", AVMEDIA_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1 }, + { 12, "QCELP", AVMEDIA_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1 }, + { 13, "CN", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 14, "MPA", AVMEDIA_TYPE_AUDIO, CODEC_ID_MP2, -1, -1 }, + { 14, "MPA", AVMEDIA_TYPE_AUDIO, CODEC_ID_MP3, -1, -1 }, + { 15, "G728", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 16, "DVI4", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1 }, + { 17, "DVI4", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1 }, + { 18, "G729", AVMEDIA_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 25, "CelB", AVMEDIA_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 26, "JPEG", AVMEDIA_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1 }, + { 28, "nv", AVMEDIA_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 31, "H261", AVMEDIA_TYPE_VIDEO, CODEC_ID_H261, 90000, -1 }, + { 32, "MPV", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1 }, + { 32, "MPV", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1 }, + { 33, "MP2T", AVMEDIA_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1 }, + { 34, "H263", AVMEDIA_TYPE_VIDEO, CODEC_ID_H263, 90000, -1 }, + { -1, "", AVMEDIA_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1 } +}; + +SessionDescriptor::DynamicPayloadDesc SessionDescriptor::smDynamicPayloads[] = { + { "MP4V-ES", AVMEDIA_TYPE_VIDEO, CODEC_ID_MPEG4 }, + { "mpeg4-generic", AVMEDIA_TYPE_AUDIO, CODEC_ID_AAC }, + { "H264", AVMEDIA_TYPE_VIDEO, CODEC_ID_H264 }, + { "AMR", AVMEDIA_TYPE_AUDIO, CODEC_ID_AMR_NB } +}; +#else +SessionDescriptor::StaticPayloadDesc SessionDescriptor::smStaticPayloads[] = { + { 0, "PCMU", CODEC_TYPE_AUDIO, CODEC_ID_PCM_MULAW, 8000, 1 }, + { 3, "GSM", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 4, "G723", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 5, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 6, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 16000, 1 }, + { 7, "LPC", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 8, "PCMA", CODEC_TYPE_AUDIO, CODEC_ID_PCM_ALAW, 8000, 1 }, + { 9, "G722", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 10, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 2 }, + { 11, "L16", CODEC_TYPE_AUDIO, CODEC_ID_PCM_S16BE, 44100, 1 }, + { 12, "QCELP", CODEC_TYPE_AUDIO, CODEC_ID_QCELP, 8000, 1 }, + { 13, "CN", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP2, -1, -1 }, + { 14, "MPA", CODEC_TYPE_AUDIO, CODEC_ID_MP3, -1, -1 }, + { 15, "G728", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 16, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 11025, 1 }, + { 17, "DVI4", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 22050, 1 }, + { 18, "G729", CODEC_TYPE_AUDIO, CODEC_ID_NONE, 8000, 1 }, + { 25, "CelB", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 26, "JPEG", CODEC_TYPE_VIDEO, CODEC_ID_MJPEG, 90000, -1 }, + { 28, "nv", CODEC_TYPE_VIDEO, CODEC_ID_NONE, 90000, -1 }, + { 31, "H261", CODEC_TYPE_VIDEO, CODEC_ID_H261, 90000, -1 }, + { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG1VIDEO, 90000, -1 }, + { 32, "MPV", CODEC_TYPE_VIDEO, CODEC_ID_MPEG2VIDEO, 90000, -1 }, + { 33, "MP2T", CODEC_TYPE_DATA, CODEC_ID_MPEG2TS, 90000, -1 }, + { 34, "H263", CODEC_TYPE_VIDEO, CODEC_ID_H263, 90000, -1 }, + { -1, "", CODEC_TYPE_UNKNOWN, CODEC_ID_NONE, -1, -1 } +}; + +SessionDescriptor::DynamicPayloadDesc SessionDescriptor::smDynamicPayloads[] = { + { "MP4V-ES", CODEC_TYPE_VIDEO, CODEC_ID_MPEG4 }, + { "mpeg4-generic", CODEC_TYPE_AUDIO, CODEC_ID_AAC }, + { "H264", CODEC_TYPE_VIDEO, CODEC_ID_H264 }, + { "AMR", CODEC_TYPE_AUDIO, CODEC_ID_AMR_NB } +}; +#endif + +SessionDescriptor::ConnInfo::ConnInfo( const std::string &connInfo ) : + mTtl( 16 ), + mNoAddresses( 0 ) +{ + StringVector tokens = split( connInfo, " " ); + if ( tokens.size() < 3 ) + throw Exception( "Unable to parse SDP connection info from '"+connInfo+"'" ); + mNetworkType = tokens[0]; + if ( mNetworkType != "IN" ) + throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); + mAddressType = tokens[1]; + if ( mAddressType != "IP4" ) + throw Exception( "Invalid SDP address type '"+mAddressType+"' in connection info '"+connInfo+"'" ); + StringVector addressTokens = split( tokens[2], "/" ); + if ( addressTokens.size() < 1 ) + throw Exception( "Invalid SDP address '"+tokens[2]+"' in connection info '"+connInfo+"'" ); + mAddress = addressTokens[0]; + if ( addressTokens.size() >= 2 ) + mTtl = atoi(addressTokens[1].c_str()); + if ( addressTokens.size() >= 3 ) + mNoAddresses = atoi(addressTokens[2].c_str()); +} + +SessionDescriptor::BandInfo::BandInfo( const std::string &bandInfo ) : + mValue( 0 ) +{ + StringVector tokens = split( bandInfo, ":" ); + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP bandwidth info from '"+bandInfo+"'" ); + mType = tokens[0]; + //if ( mNetworkType != "IN" ) + //throw Exception( "Invalid SDP network type '"+mNetworkType+"' in connection info '"+connInfo+"'" ); + mValue = atoi(tokens[1].c_str()); +} + +SessionDescriptor::MediaDescriptor::MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ) : + mType( type ), + mPort( port ), + mNumPorts( numPorts ), + mTransport( transport ), + mPayloadType( payloadType ), + mFrameRate( 0.0 ), + mClock( 0 ), + mWidth( 0 ), + mHeight( 0 ), + mConnInfo( 0 ) +{ +} + +SessionDescriptor::SessionDescriptor( const std::string &url, const std::string &sdp ) : + mUrl( url ), + mConnInfo( 0 ), + mBandInfo( 0 ) +{ + MediaDescriptor *currMedia = 0; + + StringVector lines = split( sdp, "\r\n" ); + for ( StringVector::const_iterator iter = lines.begin(); iter != lines.end(); iter++ ) + { + std::string line = *iter; + if ( line.empty() ) + break; + + Debug( 3, "Processing SDP line '%s'", line.c_str() ); + const char sdpType = line[0]; + if ( line[1] != '=' ) + throw Exception( "Invalid SDP format at '"+line+"'" ); + + line.erase( 0, 2 ); + switch( sdpType ) + { + case 'v' : + mVersion = line; + break; + case 'o' : + mOwner = line; + break; + case 's' : + mName = line; + break; + case 'i' : + mInfo = line; + break; + case 'c' : + mConnInfo = new ConnInfo( line ); + break; + case 'b' : + mBandInfo = new BandInfo( line ); + break; + case 't' : + mTimeInfo = line; + break; + case 'a' : + { + mAttributes.push_back( line ); + StringVector tokens = split( line, ":", 2 ); + std::string attrName = tokens[0]; + if ( currMedia ) + { + if ( attrName == "control" ) + { + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP control attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + currMedia->setControlUrl( tokens[1] ); + } + else if ( attrName == "range" ) + { + } + else if ( attrName == "rtpmap" ) + { + // a=rtpmap:96 MP4V-ES/90000 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP rtpmap attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " " ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + std::string payloadDesc = attrTokens[1]; + //currMedia->setPayloadType( payloadType ); + if ( attrTokens.size() > 1 ) + { + StringVector payloadTokens = split( attrTokens[1], "/" ); + std::string payloadDesc = payloadTokens[0]; + int payloadClock = atoi(payloadTokens[1].c_str()); + currMedia->setPayloadDesc( payloadDesc ); + currMedia->setClock( payloadClock ); + } + } + else if ( attrName == "framesize" ) + { + // a=framesize:96 320-240 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP framesize attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " " ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + //currMedia->setPayloadType( payloadType ); + StringVector sizeTokens = split( attrTokens[1], "-" ); + int width = atoi(sizeTokens[0].c_str()); + int height = atoi(sizeTokens[1].c_str()); + currMedia->setFrameSize( width, height ); + } + else if ( attrName == "framerate" ) + { + // a=framerate:5.0 + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP framerate attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + double frameRate = atof(tokens[1].c_str()); + currMedia->setFrameRate( frameRate ); + } + else if ( attrName == "fmtp" ) + { + // a=fmtp:96 profile-level-id=247; config=000001B0F7000001B509000001000000012008D48D8803250F042D14440F + if ( tokens.size() < 2 ) + throw Exception( "Unable to parse SDP fmtp attribute '"+line+"' for media '"+currMedia->getType()+"'" ); + StringVector attrTokens = split( tokens[1], " ", 2 ); + int payloadType = atoi(attrTokens[0].c_str()); + if ( payloadType != currMedia->getPayloadType() ) + throw Exception( stringtf( "Payload type mismatch, expected %d, got %d in '%s'", currMedia->getPayloadType(), payloadType, line.c_str() ) ); + //currMedia->setPayloadType( payloadType ); + if ( attrTokens.size() > 1 ) + { + StringVector attr2Tokens = split( attrTokens[1], "; " ); + for ( unsigned int i = 0; i < attr2Tokens.size(); i++ ) + { + StringVector attr3Tokens = split( attr2Tokens[i], "=" ); + //Info( "Name = %s, Value = %s", attr3Tokens[0].c_str(), attr3Tokens[1].c_str() ); + if ( attr3Tokens[0] == "profile-level-id" ) + { + } + else if ( attr3Tokens[0] == "config" ) + { + } + else + { + Debug( 3, "Ignoring SDP fmtp attribute '%s' for media '%s'", attr3Tokens[0].c_str(), currMedia->getType().c_str() ) + } + } + } + } + else if ( attrName == "mpeg4-iod" ) + { + // a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA" + } + else if ( attrName == "mpeg4-esid" ) + { + // a=mpeg4-esid:201 + } + else + { + Debug( 3, "Ignoring SDP attribute '%s' for media '%s'", line.c_str(), currMedia->getType().c_str() ) + } + } + else + { + Debug( 3, "Ignoring general SDP attribute '%s'", line.c_str() ); + } + break; + } + case 'm' : + { + StringVector tokens = split( line, " " ); + if ( tokens.size() < 4 ) + throw Exception( "Can't parse SDP media description '"+line+"'" ); + std::string mediaType = tokens[0]; + if ( mediaType != "audio" && mediaType != "video" ) + throw Exception( "Unsupported media type '"+mediaType+"' in SDP media attribute '"+line+"'" ); + StringVector portTokens = split( tokens[1], "/" ); + int mediaPort = atoi(portTokens[0].c_str()); + int mediaNumPorts = 1; + if ( portTokens.size() > 1 ) + mediaNumPorts = atoi(portTokens[1].c_str()); + std::string mediaTransport = tokens[2]; + if ( mediaTransport != "RTP/AVP" ) + throw Exception( "Unsupported media transport '"+mediaTransport+"' in SDP media attribute '"+line+"'" ); + int payloadType = atoi(tokens[3].c_str()); + currMedia = new MediaDescriptor( mediaType, mediaPort, mediaNumPorts, mediaTransport, payloadType ); + mMediaList.push_back( currMedia ); + break; + } + } + } +} + +AVFormatContext *SessionDescriptor::generateFormatContext() const +{ + AVFormatContext *formatContext = avformat_alloc_context(); + + strncpy( formatContext->filename, mUrl.c_str(), sizeof(formatContext->filename) ); + + //formatContext->nb_streams = mMediaList.size(); + for ( unsigned int i = 0; i < mMediaList.size(); i++ ) + { + const MediaDescriptor *mediaDesc = mMediaList[i]; +#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(53, 8, 0) + AVStream *stream = av_new_stream( formatContext, i ); +#else + AVStream *stream = avformat_new_stream( formatContext, NULL ); + stream->id = i; +#endif + + Debug( 1, "Looking for codec for %s payload type %d / %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); +#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,2,1) + if ( mediaDesc->getType() == "video" ) + stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; + else if ( mediaDesc->getType() == "audio" ) + stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; +#else + if ( mediaDesc->getType() == "video" ) + stream->codec->codec_type = CODEC_TYPE_VIDEO; + else if ( mediaDesc->getType() == "audio" ) + stream->codec->codec_type = CODEC_TYPE_AUDIO; +#endif + + if ( mediaDesc->getPayloadType() < PAYLOAD_TYPE_DYNAMIC ) + { + // Look in static table + for ( unsigned int i = 0; i < (sizeof(smStaticPayloads)/sizeof(*smStaticPayloads)); i++ ) + { + if ( smStaticPayloads[i].payloadType == mediaDesc->getPayloadType() ) + { + Debug( 1, "Got static payload type %d, %s", smStaticPayloads[i].payloadType, smStaticPayloads[i].payloadName ); + strncpy( stream->codec->codec_name, smStaticPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; + stream->codec->codec_type = smStaticPayloads[i].codecType; + stream->codec->codec_id = smStaticPayloads[i].codecId; + stream->codec->sample_rate = smStaticPayloads[i].clockRate; + break; + } + } + } + else + { + // Look in dynamic table + for ( unsigned int i = 0; i < (sizeof(smDynamicPayloads)/sizeof(*smDynamicPayloads)); i++ ) + { + if ( smDynamicPayloads[i].payloadName == mediaDesc->getPayloadDesc() ) + { + Debug( 1, "Got dynamic payload type %d, %s", mediaDesc->getPayloadType(), smDynamicPayloads[i].payloadName ); + strncpy( stream->codec->codec_name, smDynamicPayloads[i].payloadName, sizeof(stream->codec->codec_name) );; + stream->codec->codec_type = smDynamicPayloads[i].codecType; + stream->codec->codec_id = smDynamicPayloads[i].codecId; + stream->codec->sample_rate = mediaDesc->getClock(); + break; + } + } + } + if ( !stream->codec->codec_name[0] ) + { + Warning( "Can't find payload details for %s payload type %d, name %s", mediaDesc->getType().c_str(), mediaDesc->getPayloadType(), mediaDesc->getPayloadDesc().c_str() ); + //return( 0 ); + } + if ( mediaDesc->getWidth() ) + stream->codec->width = mediaDesc->getWidth(); + if ( mediaDesc->getHeight() ) + stream->codec->height = mediaDesc->getHeight(); + } + + return( formatContext ); +} + +#endif // HAVE_LIBAVFORMAT diff --git a/src/zm_sdp.h b/src/zm_sdp.h new file mode 100644 index 000000000..6d4291f45 --- /dev/null +++ b/src/zm_sdp.h @@ -0,0 +1,241 @@ +// +// ZoneMinder SDP Class Interface, $Date: 2009-02-16 18:21:50 +0000 (Mon, 16 Feb 2009) $, $Revision: 2765 $ +// 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. +// + +#ifndef ZM_SDP_H +#define ZM_SDP_H + +#include "zm.h" + +#include "zm_utils.h" +#include "zm_exception.h" +#include "zm_ffmpeg.h" + +#include + +#include +#include + +class SessionDescriptor +{ +protected: + enum { PAYLOAD_TYPE_DYNAMIC=96 }; + + struct StaticPayloadDesc + { + int payloadType; + const char payloadName[6]; + enum AVMediaType codecType; + enum CodecID codecId; + int clockRate; + int autoChannels; + }; + + struct DynamicPayloadDesc + { + const char payloadName[32]; + enum AVMediaType codecType; + enum CodecID codecId; + //int clockRate; + //int autoChannels; + }; + +public: + class ConnInfo + { + protected: + std::string mNetworkType; + std::string mAddressType; + std::string mAddress; + int mTtl; + int mNoAddresses; + + public: + ConnInfo( const std::string &connInfo ); + }; + + class BandInfo + { + protected: + std::string mType; + int mValue; + + public: + BandInfo( const std::string &bandInfo ); + }; + + class MediaDescriptor + { + protected: + std::string mType; + int mPort; + int mNumPorts; + std::string mTransport; + int mPayloadType; + + std::string mPayloadDesc; + std::string mControlUrl; + double mFrameRate; + int mClock; + int mWidth; + int mHeight; + + ConnInfo *mConnInfo; + + public: + MediaDescriptor( const std::string &type, int port, int numPorts, const std::string &transport, int payloadType ); + + const std::string &getType() const + { + return( mType ); + } + int getPort() const + { + return( mPort ); + } + int getNumPorts() const + { + return( mNumPorts ); + } + const std::string &getTransport() const + { + return( mTransport ); + } + const int getPayloadType() const + { + return( mPayloadType ); + } + + const std::string &getPayloadDesc() const + { + return( mPayloadDesc ); + } + void setPayloadDesc( const std::string &payloadDesc ) + { + mPayloadDesc = payloadDesc; + } + + const std::string &getControlUrl() const + { + return( mControlUrl ); + } + void setControlUrl( const std::string &controlUrl ) + { + mControlUrl = controlUrl; + } + + const int getClock() const + { + return( mClock ); + } + void setClock( int clock ) + { + mClock = clock; + } + + void setFrameSize( int width, int height ) + { + mWidth = width; + mHeight = height; + } + int getWidth() const + { + return( mWidth ); + } + int getHeight() const + { + return( mHeight ); + } + + const double getFrameRate() const + { + return( mFrameRate ); + } + void setFrameRate( double frameRate ) + { + mFrameRate = frameRate; + } + }; + + typedef std::vector MediaList; + +protected: + static StaticPayloadDesc smStaticPayloads[]; + static DynamicPayloadDesc smDynamicPayloads[]; + +protected: + std::string mUrl; + + std::string mVersion; + std::string mOwner; + std::string mName; + std::string mInfo; + + ConnInfo *mConnInfo; + BandInfo *mBandInfo; + std::string mTimeInfo; + StringVector mAttributes; + + MediaList mMediaList; + +public: + SessionDescriptor( const std::string &url, const std::string &sdp ); + + const std::string &getUrl() const + { + return( mUrl ); + } + + int getNumStreams() const + { + return( mMediaList.size() ); + } + MediaDescriptor *getStream( int index ) + { + if ( index < 0 || (unsigned int)index >= mMediaList.size() ) + return( 0 ); + return( mMediaList[index] ); + } + + AVFormatContext *generateFormatContext() const; +}; +#if 0 +v=0 +o=- 1239719297054659 1239719297054674 IN IP4 192.168.1.11 +s=Media Presentation +e=NONE +c=IN IP4 0.0.0.0 +b=AS:174 +t=0 0 +a=control:* +a=range:npt=now- +a=mpeg4-iod: "data:application/mpeg4-iod;base64,AoEAAE8BAf73AQOAkwABQHRkYXRhOmFwcGxpY2F0aW9uL21wZWc0LW9kLWF1O2Jhc2U2NCxBVGdCR3dVZkF4Y0F5U1FBWlFRTklCRUVrK0FBQWEyd0FBR3RzQVlCQkFFWkFwOERGUUJsQlFRTlFCVUFDN2dBQVBvQUFBRDZBQVlCQXc9PQQNAQUABAAAAAAAAAAAAAYJAQAAAAAAAAAAA0IAAkA+ZGF0YTphcHBsaWNhdGlvbi9tcGVnNC1iaWZzLWF1O2Jhc2U2NCx3QkFTZ1RBcUJYSmhCSWhRUlFVL0FBPT0EEgINAAACAAAAAAAAAAAFAwAAQAYJAQAAAAAAAAAA" +m=video 0 RTP/AVP 96 +b=AS:110 +a=framerate:5.0 +a=control:trackID=1 +a=rtpmap:96 MP4V-ES/90000 +a=fmtp:96 profile-level-id=247; config=000001B0F7000001B509000001000000012008D48D8803250F042D14440F +a=mpeg4-esid:201 +m=audio 0 RTP/AVP 0 +b=AS:64 +a=control:trackID=2 + +#endif + +#endif // ZM_SDP_H diff --git a/src/zm_signal.cpp b/src/zm_signal.cpp new file mode 100644 index 000000000..5bb000f0b --- /dev/null +++ b/src/zm_signal.cpp @@ -0,0 +1,197 @@ +// +// ZoneMinder Signal Handling Implementation, $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. +// + +#include "zm.h" +#include "zm_signal.h" + +#include +#include +#include + +bool zm_reload = false; + +RETSIGTYPE zm_hup_handler( int signal ) +{ +#if HAVE_STRSIGNAL + Info( "Got signal %d (%s), reloading", signal, strsignal(signal) ); +#else // HAVE_STRSIGNAL + Info( "Got HUP signal, reloading" ); +#endif // HAVE_STRSIGNAL + zm_reload = true; +} + +bool zm_terminate = false; + +RETSIGTYPE zm_term_handler( int signal ) +{ +#if HAVE_STRSIGNAL + Info( "Got signal %d (%s), exiting", signal, strsignal(signal) ); +#else // HAVE_STRSIGNAL + Info( "Got TERM signal, exiting" ); +#endif // HAVE_STRSIGNAL + zm_terminate = true; +} + +#define TRACE_SIZE 16 + +#if HAVE_STRUCT_SIGCONTEXT +RETSIGTYPE zm_die_handler( int signal, struct sigcontext context ) +#elif ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) +#include +RETSIGTYPE zm_die_handler( int signal, siginfo_t *info, void *context ) +#else +RETSIGTYPE zm_die_handler( int signal ) +#endif +{ + if ( signal == SIGABRT ) + { +#if HAVE_STRSIGNAL + Info( "Got signal %d (%s), exiting and forcing backtrace", signal, strsignal(signal) ); +#else // HAVE_STRSIGNAL + Error( "Got signal %d, exiting and forcing backtrace", signal ); +#endif // HAVE_STRSIGNAL + } + else + { +#if HAVE_STRSIGNAL + Info( "Got signal %d (%s), crashing", signal, strsignal(signal) ); +#else // HAVE_STRSIGNAL + Error( "Got signal %d, crashing", signal ); +#endif // HAVE_STRSIGNAL + } + +#ifndef ZM_NO_CRASHTRACE +#if ( ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT ) + void *trace[TRACE_SIZE]; + int trace_size = 0; + +#if HAVE_STRUCT_SIGCONTEXT_EIP + Error( "Signal address is %p, from %p", (void *)context.cr2, (void *)context.eip ); + + trace_size = backtrace( trace, TRACE_SIZE ); + // overwrite sigaction with caller's address + trace[1] = (void *)context.eip; +#elif HAVE_STRUCT_SIGCONTEXT + Error( "Signal address is %p, no eip", (void *)context.cr2 ); + + trace_size = backtrace( trace, TRACE_SIZE ); +#else // HAVE_STRUCT_SIGCONTEXT + if ( info && context ) + { + ucontext_t *uc = (ucontext_t *)context; + + Error( "Signal address is %p, from %p", info->si_addr, uc->uc_mcontext.gregs[REG_EIP] ); + + trace_size = backtrace( trace, TRACE_SIZE ); + // overwrite sigaction with caller's address + trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP]; + } +#endif // HAVE_STRUCT_SIGCONTEXT +#if HAVE_DECL_BACKTRACE + char cmd[1024] = "addr2line -e "; + char *cmd_ptr = cmd+strlen(cmd); + // Try and extract the binary path from the last backtrace frame + char **messages = backtrace_symbols( trace, trace_size ); + if ( size_t offset = strcspn( messages[trace_size-1], " " ) ) + { + snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), messages[trace_size-1] ); + cmd_ptr += offset; + } + else + { + cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), "/path/to/%s", logId().c_str() ); + } + // skip first stack frame (points here) + for ( int i=1; i < trace_size; i++ ) + { + Error( "Backtrace: %s", messages[i] ); + cmd_ptr += snprintf( cmd_ptr, sizeof(cmd)-(cmd_ptr-cmd), " %p", trace[i] ); + } + Info( "Backtrace complete, please execute the following command for more information" ); + Info( cmd ); +#endif // HAVE_DECL_BACKTRACE +#endif // ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) || HAVE_STRUCT_SIGCONTEXT +#endif // ZM_NO_CRASHTRACE + + exit( signal ); +} + +void zmSetHupHandler( SigHandler *handler ) +{ + sigset_t block_set; + sigemptyset( &block_set ); + struct sigaction action, old_action; + + action.sa_handler = (SigHandler *)handler; + action.sa_mask = block_set; + action.sa_flags = 0; + sigaction( SIGHUP, &action, &old_action ); +} + +void zmSetTermHandler( SigHandler *handler ) +{ + sigset_t block_set; + sigemptyset( &block_set ); + struct sigaction action, old_action; + + action.sa_handler = (SigHandler *)handler; + action.sa_mask = block_set; + action.sa_flags = 0; + sigaction( SIGTERM, &action, &old_action ); +} + +void zmSetDieHandler( SigHandler *handler ) +{ + sigset_t block_set; + sigemptyset( &block_set ); + struct sigaction action, old_action; + + action.sa_handler = (SigHandler *)handler; + action.sa_mask = block_set; + action.sa_flags = 0; + + sigaction( SIGBUS, &action, &old_action ); + sigaction( SIGSEGV, &action, &old_action ); + sigaction( SIGABRT, &action, &old_action ); + sigaction( SIGILL, &action, &old_action ); + sigaction( SIGFPE, &action, &old_action ); +} + +void zmSetDefaultHupHandler() +{ + zmSetHupHandler( (SigHandler *)zm_hup_handler ); +} + +void zmSetDefaultTermHandler() +{ + zmSetTermHandler( (SigHandler *)zm_term_handler ); +} + +void zmSetDefaultDieHandler() +{ + if ( config.dump_cores ) + { + // Do nothing + } + else + { + zmSetDieHandler( (SigHandler *)zm_die_handler ); + } +} + diff --git a/src/zm_signal.h b/src/zm_signal.h new file mode 100644 index 000000000..f899e19fc --- /dev/null +++ b/src/zm_signal.h @@ -0,0 +1,52 @@ +/* + * ZoneMinder Signal Handling Interface, $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. +*/ + +#ifndef ZM_SIGNAL_H +#define ZM_SIGNAL_H + +#include +#include + +#include "zm.h" + +typedef RETSIGTYPE (SigHandler)( int ); + +extern bool zm_reload; +extern bool zm_terminate; + +RETSIGTYPE zmc_hup_handler( int signal ); +RETSIGTYPE zmc_term_handler( int signal ); +#if HAVE_STRUCT_SIGCONTEXT +RETSIGTYPE zmc_die_handler( int signal, struct sigcontext context ); +#elif ( HAVE_SIGINFO_T && HAVE_UCONTEXT_T ) +#include +RETSIGTYPE zmc_die_handler( int signal, siginfo_t *info, void *context ); +#else +RETSIGTYPE zmc_die_handler( int signal ); +#endif + +void zmSetHupHandler( SigHandler *handler ); +void zmSetTermHandler( SigHandler *handler ); +void zmSetDieHandler( SigHandler *handler ); + +void zmSetDefaultHupHandler(); +void zmSetDefaultTermHandler(); +void zmSetDefaultDieHandler(); + +#endif // ZM_SIGNAL_H diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp new file mode 100644 index 000000000..2cea2f10b --- /dev/null +++ b/src/zm_stream.cpp @@ -0,0 +1,318 @@ +// +// ZoneMinder Stream Class Implementation, $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. +// + +#include + +#include "zm.h" +#include "zm_mpeg.h" +#include "zm_monitor.h" + +#include "zm_stream.h" + +StreamBase::~StreamBase() +{ + closeComms(); +} + +bool StreamBase::loadMonitor( int monitor_id ) +{ + if ( !(monitor = Monitor::Load( monitor_id, false, Monitor::QUERY )) ) + { + Fatal( "Unable to load monitor id %d for streaming", monitor_id ); + return( false ); + } + return( true ); +} + +bool StreamBase::checkInitialised() +{ + if ( !monitor ) + { + Fatal( "Cannot stream, not initialised" ); + return( false ); + } + return( true ); +} + +void StreamBase::updateFrameRate( double fps ) +{ + base_fps = fps; + effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; + frame_mod = 1; + Debug( 3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod ); + // Min frame repeat? + while( effective_fps > maxfps ) + { + effective_fps /= 2.0; + frame_mod *= 2; + } + Debug( 3, "aEFPS:%.2f, aFM:%d", effective_fps, frame_mod ); +} + +bool StreamBase::checkCommandQueue() +{ + if ( sd >= 0 ) + { + CmdMsg msg; + memset( &msg, 0, sizeof(msg) ); + int nbytes = recvfrom( sd, &msg, sizeof(msg), MSG_DONTWAIT, 0, 0 ); + if ( nbytes < 0 ) + { + if ( errno != EAGAIN ) + { + Fatal( "recvfrom(), errno = %d, error = %s", errno, strerror(errno) ); + } + } + //else if ( (nbytes != sizeof(msg)) ) + //{ + //Error( "Partial message received, expected %d bytes, got %d", sizeof(msg), nbytes ); + //} + else + { + processCommand( &msg ); + return( true ); + } + } + return( false ); +} + +Image *StreamBase::prepareImage( Image *image ) +{ + static int last_scale = 0; + static int last_zoom = 0; + static int last_x = 0; + static int last_y = 0; + + if ( !last_scale ) + last_scale = scale; + if ( !last_zoom ) + last_zoom = zoom; + + // Do not bother to scale zoomed in images, just crop them and let the browser scale + // Works in FF2 but breaks FF3 which doesn't like image sizes changing in mid stream. + bool optimisedScaling = false; + + bool image_copied = false; + + int mag = (scale * zoom) / ZM_SCALE_BASE; + int act_mag = optimisedScaling?(mag > ZM_SCALE_BASE?ZM_SCALE_BASE:mag):mag; + Debug( 3, "Scaling by %d, zooming by %d = magnifying by %d(%d)", scale, zoom, mag, act_mag ); + + int last_mag = (last_scale * last_zoom) / ZM_SCALE_BASE; + int last_act_mag = last_mag > ZM_SCALE_BASE?ZM_SCALE_BASE:last_mag; + Debug( 3, "Last scaling by %d, zooming by %d = magnifying by %d(%d)", last_scale, last_zoom, last_mag, last_act_mag ); + + int base_image_width = image->Width(), base_image_height = image->Height(); + Debug( 3, "Base image width = %d, height = %d", base_image_width, base_image_height ); + + int virt_image_width = (base_image_width * mag) / ZM_SCALE_BASE, virt_image_height = (base_image_height * mag) / ZM_SCALE_BASE; + Debug( 3, "Virtual image width = %d, height = %d", virt_image_width, virt_image_height ); + + int last_virt_image_width = (base_image_width * last_mag) / ZM_SCALE_BASE, last_virt_image_height = (base_image_height * last_mag) / ZM_SCALE_BASE; + Debug( 3, "Last virtual image width = %d, height = %d", last_virt_image_width, last_virt_image_height ); + + int act_image_width = (base_image_width * act_mag ) / ZM_SCALE_BASE, act_image_height = (base_image_height * act_mag ) / ZM_SCALE_BASE; + Debug( 3, "Actual image width = %d, height = %d", act_image_width, act_image_height ); + + int last_act_image_width = (base_image_width * last_act_mag ) / ZM_SCALE_BASE, last_act_image_height = (base_image_height * last_act_mag ) / ZM_SCALE_BASE; + Debug( 3, "Last actual image width = %d, height = %d", last_act_image_width, last_act_image_height ); + + int disp_image_width = (image->Width() * scale) / ZM_SCALE_BASE, disp_image_height = (image->Height() * scale) / ZM_SCALE_BASE; + Debug( 3, "Display image width = %d, height = %d", disp_image_width, disp_image_height ); + + int last_disp_image_width = (image->Width() * last_scale) / ZM_SCALE_BASE, last_disp_image_height = (image->Height() * last_scale) / ZM_SCALE_BASE; + Debug( 3, "Last display image width = %d, height = %d", last_disp_image_width, last_disp_image_height ); + + int send_image_width = (disp_image_width * act_mag ) / mag, send_image_height = (disp_image_height * act_mag ) / mag; + Debug( 3, "Send image width = %d, height = %d", send_image_width, send_image_height ); + + int last_send_image_width = (last_disp_image_width * last_act_mag ) / last_mag, last_send_image_height = (last_disp_image_height * last_act_mag ) / last_mag; + Debug( 3, "Last send image width = %d, height = %d", last_send_image_width, last_send_image_height ); + + if ( mag != ZM_SCALE_BASE ) + { + if ( act_mag != ZM_SCALE_BASE ) + { + Debug( 3, "Magnifying by %d", mag ); + if ( !image_copied ) + { + static Image copy_image; + copy_image.Assign( *image ); + image = ©_image; + image_copied = true; + } + image->Scale( mag ); + } + } + + Debug( 3, "Real image width = %d, height = %d", image->Width(), image->Height() ); + + if ( disp_image_width < virt_image_width || disp_image_height < virt_image_height ) + { + static Box last_crop; + + if ( mag != last_mag || x != last_x || y != last_y ) + { + Debug( 3, "Got click at %d,%d x %d", x, y, mag ); + + //if ( !last_mag ) + //last_mag = mag; + + if ( !(last_disp_image_width < last_virt_image_width || last_disp_image_height < last_virt_image_height) ) + last_crop = Box(); + + Debug( 3, "Recalculating crop" ); + // Recalculate crop parameters, as %ges + int click_x = (last_crop.LoX() * 100 ) / last_act_image_width; // Initial crop offset from last image + click_x += ( x * 100 ) / last_virt_image_width; + int click_y = (last_crop.LoY() * 100 ) / last_act_image_height; // Initial crop offset from last image + click_y += ( y * 100 ) / last_virt_image_height; + Debug( 3, "Got adjusted click at %d%%,%d%%", click_x, click_y ); + + // Convert the click locations to the current image pixels + click_x = ( click_x * act_image_width ) / 100; + click_y = ( click_y * act_image_height ) / 100; + Debug( 3, "Got readjusted click at %d,%d", click_x, click_y ); + + int lo_x = click_x - (send_image_width/2); + if ( lo_x < 0 ) + lo_x = 0; + int hi_x = lo_x + (send_image_width-1); + if ( hi_x >= act_image_width ) + { + hi_x = act_image_width - 1; + lo_x = hi_x - (send_image_width - 1); + } + + int lo_y = click_y - (send_image_height/2); + if ( lo_y < 0 ) + lo_y = 0; + int hi_y = lo_y + (send_image_height-1); + if ( hi_y >= act_image_height ) + { + hi_y = act_image_height - 1; + lo_y = hi_y - (send_image_height - 1); + } + last_crop = Box( lo_x, lo_y, hi_x, hi_y ); + } + Debug( 3, "Cropping to %d,%d -> %d,%d", last_crop.LoX(), last_crop.LoY(), last_crop.HiX(), last_crop.HiY() ); + if ( !image_copied ) + { + static Image copy_image; + copy_image.Assign( *image ); + image = ©_image; + image_copied = true; + } + image->Crop( last_crop ); + } + last_scale = scale; + last_zoom = zoom; + last_x = x; + last_y = y; + + return( image ); +} + +bool StreamBase::sendTextFrame( const char *frame_text ) +{ + Debug( 2, "Sending text frame '%s'", frame_text ); + + Image image( monitor->Width(), monitor->Height(), monitor->Colours(), monitor->SubpixelOrder() ); + image.Annotate( frame_text, image.centreCoord( frame_text ) ); + + if ( scale != 100 ) + { + image.Scale( scale ); + } +#if HAVE_LIBAVCODEC + if ( type == STREAM_MPEG ) + { + if ( !vid_stream ) + { + vid_stream = new VideoStream( "pipe:", format, bitrate, effective_fps, image.Colours(), image.SubpixelOrder(), image.Width(), image.Height() ); + fprintf( stdout, "Content-type: %s\r\n\r\n", vid_stream->MimeType() ); + vid_stream->OpenStream(); + } + /* double pts = */ vid_stream->EncodeFrame( image.Buffer(), image.Size() ); + } + else +#endif // HAVE_LIBAVCODEC + { + static unsigned char buffer[ZM_MAX_IMAGE_SIZE]; + int n_bytes = 0; + + image.EncodeJpeg( buffer, &n_bytes ); + + fprintf( stdout, "--ZoneMinderFrame\r\n" ); + fprintf( stdout, "Content-Length: %d\r\n", n_bytes ); + fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" ); + if ( fwrite( buffer, n_bytes, 1, stdout ) != 1 ) + { + Error( "Unable to send stream text frame: %s", strerror(errno) ); + return( false ); + } + fprintf( stdout, "\r\n\r\n" ); + fflush( stdout ); + } + last_frame_sent = TV_2_FLOAT( now ); + return( true ); +} + +void StreamBase::openComms() +{ + if ( connkey > 0 ) + { + sd = socket( AF_UNIX, SOCK_DGRAM, 0 ); + if ( sd < 0 ) + { + Fatal( "Can't create socket: %s", strerror(errno) ); + } + + snprintf( loc_sock_path, sizeof(loc_sock_path), "%s/zms-%06ds.sock", config.path_socks, connkey ); + unlink( loc_sock_path ); + + strncpy( loc_addr.sun_path, loc_sock_path, sizeof(loc_addr.sun_path) ); + loc_addr.sun_family = AF_UNIX; + if ( bind( sd, (struct sockaddr *)&loc_addr, strlen(loc_addr.sun_path)+sizeof(loc_addr.sun_family)) < 0 ) + { + Fatal( "Can't bind: %s", strerror(errno) ); + } + + snprintf( rem_sock_path, sizeof(rem_sock_path), "%s/zms-%06dw.sock", config.path_socks, connkey ); + strncpy( rem_addr.sun_path, rem_sock_path, sizeof(rem_addr.sun_path) ); + rem_addr.sun_family = AF_UNIX; + } +} + +void StreamBase::closeComms() +{ + if ( connkey > 0 ) + { + if ( sd >= 0 ) + { + close( sd ); + sd = -1; + } + if ( loc_sock_path[0] ) + { + unlink( loc_sock_path ); + } + } +} + diff --git a/src/zm_stream.h b/src/zm_stream.h new file mode 100644 index 000000000..22f8b153d --- /dev/null +++ b/src/zm_stream.h @@ -0,0 +1,178 @@ +// +// ZoneMinder Stream Interfaces, $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. +// + +#ifndef ZM_STREAM_H +#define ZM_STREAM_H + +#include +#include + +#include "zm.h" +#include "zm_mpeg.h" + +class Monitor; + +#define TV_2_FLOAT( tv ) ( double((tv).tv_sec) + (double((tv).tv_usec) / 1000000.0) ) + +class StreamBase +{ +public: + typedef enum { STREAM_JPEG, STREAM_RAW, STREAM_ZIP, STREAM_SINGLE, STREAM_MPEG } StreamType; + +protected: + static const int MAX_STREAM_DELAY = 5; // Seconds + + static const StreamType DEFAULT_TYPE = STREAM_JPEG; + enum { DEFAULT_RATE=ZM_RATE_BASE }; + enum { DEFAULT_SCALE=ZM_SCALE_BASE }; + enum { DEFAULT_ZOOM=ZM_SCALE_BASE }; + enum { DEFAULT_MAXFPS=10 }; + enum { DEFAULT_BITRATE=100000 }; + +protected: + typedef struct { + int msg_type; + char msg_data[16]; + } CmdMsg; + + typedef struct { + int msg_type; + char msg_data[256]; + } DataMsg; + + 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_QUERY=99 } MsgCommand; + +protected: + Monitor *monitor; + + StreamType type; + const char *format; + int replay_rate; + int scale; + int zoom; + double maxfps; + int bitrate; + unsigned short x, y; + +protected: + int connkey; + int sd; + char loc_sock_path[PATH_MAX]; + struct sockaddr_un loc_addr; + char rem_sock_path[PATH_MAX]; + struct sockaddr_un rem_addr; + +protected: + bool paused; + int step; + + struct timeval now; + + double base_fps; + double effective_fps; + int frame_mod; + + double last_frame_sent; + struct timeval last_frame_timestamp; + +#if HAVE_LIBAVCODEC + VideoStream *vid_stream; +#endif // HAVE_LIBAVCODEC + + CmdMsg msg; + +protected: + bool loadMonitor( int monitor_id ); + bool checkInitialised(); + void updateFrameRate( double fps ); + Image *prepareImage( Image *image ); + bool sendTextFrame( const char *text ); + bool checkCommandQueue(); + virtual void processCommand( const CmdMsg *msg )=0; + +public: + StreamBase() + { + monitor = 0; + + type = DEFAULT_TYPE; + format = ""; + replay_rate = DEFAULT_RATE; + scale = DEFAULT_SCALE; + zoom = DEFAULT_ZOOM; + maxfps = DEFAULT_MAXFPS; + bitrate = DEFAULT_BITRATE; + + paused = false; + step = 0; + x = 0; + y = 0; + + connkey = 0; + sd = -1; + memset( &loc_sock_path, 0, sizeof(loc_sock_path) ); + memset( &loc_addr, 0, sizeof(loc_addr) ); + memset( &rem_sock_path, 0, sizeof(rem_sock_path) ); + memset( &rem_addr, 0, sizeof(rem_addr) ); + + base_fps = 0.0; + effective_fps = 0.0; + frame_mod = 1; + +#if HAVE_LIBAVCODEC + vid_stream = 0; +#endif // HAVE_LIBAVCODEC + } + virtual ~StreamBase(); + + void setStreamType( StreamType p_type ) + { + type = p_type; + } + void setStreamFormat( const char *p_format ) + { + format = p_format; + } + void setStreamScale( int p_scale ) + { + scale = p_scale; + } + void setStreamReplayRate( int p_rate ) + { + replay_rate = p_rate; + } + void setStreamMaxFPS( double p_maxfps ) + { + maxfps = p_maxfps; + } + void setStreamBitrate( int p_bitrate ) + { + bitrate = p_bitrate; + } + void setStreamQueue( int p_connkey ) + { + connkey = p_connkey; + } + virtual void openComms(); + virtual void closeComms(); + virtual void runStream()=0; +}; + +#endif // ZM_STREAM_H diff --git a/src/zm_thread.cpp b/src/zm_thread.cpp new file mode 100644 index 000000000..09cf0da3f --- /dev/null +++ b/src/zm_thread.cpp @@ -0,0 +1,340 @@ +// +// ZoneMinder Thread Class Implementation, $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. +// + +#include "zm_thread.h" + +#include "zm_logger.h" +#include "zm_utils.h" + +#include +#include +#include +#include + +struct timespec getTimeout( int secs ) +{ + struct timespec timeout; + struct timeval temp_timeout; + gettimeofday( &temp_timeout, 0 ); + timeout.tv_sec = temp_timeout.tv_sec + secs; + timeout.tv_nsec = temp_timeout.tv_usec*1000; + return( timeout ); +} + +struct timespec getTimeout( double secs ) +{ + struct timespec timeout; + struct timeval temp_timeout; + gettimeofday( &temp_timeout, 0 ); + timeout.tv_sec = temp_timeout.tv_sec + int(secs); + timeout.tv_nsec = temp_timeout.tv_usec += (long int)(1000000000.0*(secs-int(secs))); + if ( timeout.tv_nsec > 1000000000 ) + { + timeout.tv_sec += 1; + timeout.tv_nsec -= 1000000000; + } + return( timeout ); +} + +Mutex::Mutex() +{ + if ( pthread_mutex_init( &mMutex, NULL ) < 0 ) + throw ThreadException( stringtf( "Unable to create pthread mutex: %s", strerror(errno) ) ); +} + +Mutex::~Mutex() +{ + if ( locked() ) + Warning( "Destroying mutex when locked" ); + if ( pthread_mutex_destroy( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to destroy pthread mutex: %s", strerror(errno) ) ); +} + +void Mutex::lock() +{ + if ( pthread_mutex_lock( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to lock pthread mutex: %s", strerror(errno) ) ); +} + +void Mutex::lock( int secs ) +{ + struct timespec timeout = getTimeout( secs ); + if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) + throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); +} + +void Mutex::lock( double secs ) +{ + struct timespec timeout = getTimeout( secs ); + if ( pthread_mutex_timedlock( &mMutex, &timeout ) < 0 ) + throw ThreadException( stringtf( "Unable to timedlock pthread mutex: %s", strerror(errno) ) ); +} + +void Mutex::unlock() +{ + if ( pthread_mutex_unlock( &mMutex ) < 0 ) + throw ThreadException( stringtf( "Unable to unlock pthread mutex: %s", strerror(errno) ) ); +} + +bool Mutex::locked() +{ + int state = pthread_mutex_trylock( &mMutex ); + if ( state != 0 && state != EBUSY ) + throw ThreadException( stringtf( "Unable to trylock pthread mutex: %s", strerror(errno) ) ); + if ( state != EBUSY ) + unlock(); + return( state == EBUSY ); +} + +Condition::Condition( Mutex &mutex ) : mMutex( mutex ) +{ + if ( pthread_cond_init( &mCondition, NULL ) < 0 ) + throw ThreadException( stringtf( "Unable to create pthread condition: %s", strerror(errno) ) ); +} + +Condition::~Condition() +{ + if ( pthread_cond_destroy( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to destroy pthread condition: %s", strerror(errno) ) ); +} + +void Condition::wait() +{ + // Locking done outside of this function + if ( pthread_cond_wait( &mCondition, mMutex.getMutex() ) < 0 ) + throw ThreadException( stringtf( "Unable to wait pthread condition: %s", strerror(errno) ) ); +} + +bool Condition::wait( int secs ) +{ + // Locking done outside of this function + Debug( 8, "Waiting for %d seconds", secs ); + struct timespec timeout = getTimeout( secs ); + if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) + throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); + return( errno != ETIMEDOUT ); +} + +bool Condition::wait( double secs ) +{ + // Locking done outside of this function + struct timespec timeout = getTimeout( secs ); + if ( pthread_cond_timedwait( &mCondition, mMutex.getMutex(), &timeout ) < 0 && errno != ETIMEDOUT ) + throw ThreadException( stringtf( "Unable to timedwait pthread condition: %s", strerror(errno) ) ); + return( errno != ETIMEDOUT ); +} + +void Condition::signal() +{ + if ( pthread_cond_signal( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to signal pthread condition: %s", strerror(errno) ) ); +} + +void Condition::broadcast() +{ + if ( pthread_cond_broadcast( &mCondition ) < 0 ) + throw ThreadException( stringtf( "Unable to broadcast pthread condition: %s", strerror(errno) ) ); +} + +template const T ThreadData::getValue() const +{ + mMutex.lock(); + const T valueCopy = mValue; + mMutex.unlock(); + return( valueCopy ); +} + +template T ThreadData::setValue( const T value ) +{ + mMutex.lock(); + const T valueCopy = mValue = value; + mMutex.unlock(); + return( valueCopy ); +} + +template const T ThreadData::getUpdatedValue() const +{ + Debug( 8, "Waiting for value update, %p", this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait(); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); +} + +template const T ThreadData::getUpdatedValue( double secs ) const +{ + Debug( 8, "Waiting for value update, %.2f secs, %p", secs, this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait( secs ); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); +} + +template const T ThreadData::getUpdatedValue( int secs ) const +{ + Debug( 8, "Waiting for value update, %d secs, %p", secs, this ); + mMutex.lock(); + mChanged = false; + //do { + mCondition.wait( secs ); + //} while ( !mChanged ); + const T valueCopy = mValue; + mMutex.unlock(); + Debug( 9, "Got value update, %p", this ); + return( valueCopy ); +} + +template void ThreadData::updateValueSignal( const T value ) +{ + Debug( 8, "Updating value with signal, %p", this ); + mMutex.lock(); + mValue = value; + mChanged = true; + mCondition.signal(); + mMutex.unlock(); + Debug( 9, "Updated value, %p", this ); +} + +template void ThreadData::updateValueBroadcast( const T value ) +{ + Debug( 8, "Updating value with broadcast, %p", this ); + mMutex.lock(); + mValue = value; + mChanged = true; + mCondition.broadcast(); + mMutex.unlock(); + Debug( 9, "Updated value, %p", this ); +} + +Thread::Thread() : + mThreadCondition( mThreadMutex ), + mPid( -1 ), + mStarted( false ), + mRunning( false ) +{ + Debug( 1, "Creating thread" ); +} + +Thread::~Thread() +{ + Debug( 1, "Destroying thread %d", mPid ); + if ( mStarted ) + join(); +} + +void *Thread::mThreadFunc( void *arg ) +{ + Debug( 2, "Invoking thread" ); + + Thread *thisPtr = (Thread *)arg; + void *status = 0; + try + { + thisPtr->mThreadMutex.lock(); + thisPtr->mPid = thisPtr->id(); + thisPtr->mThreadCondition.signal(); + thisPtr->mThreadMutex.unlock(); + thisPtr->mRunning = true; + int run=(thisPtr->run()); + status = (void *)&run; + thisPtr->mRunning = false; + Debug( 2, "Exiting thread, status %p", status ); + } + catch ( const ThreadException &e ) + { + Error( "%s", e.getMessage().c_str() ); + thisPtr->mRunning = false; + status = (void *)-1; + Debug( 2, "Exiting thread after exception, status %p", status ); + } + return( status ); +} + +void Thread::start() +{ + Debug( 1, "Starting thread" ); + if ( isThread() ) + throw ThreadException( "Can't self start thread" ); + mThreadMutex.lock(); + if ( !mStarted ) + { + pthread_attr_t threadAttrs; + pthread_attr_init( &threadAttrs ); + pthread_attr_setscope( &threadAttrs, PTHREAD_SCOPE_SYSTEM ); + + mStarted = true; + if ( pthread_create( &mThread, &threadAttrs, mThreadFunc, this ) < 0 ) + throw ThreadException( stringtf( "Can't create thread: %s", strerror(errno) ) ); + pthread_attr_destroy( &threadAttrs ); + } + else + { + Error( "Attempt to start already running thread %d", mPid ); + } + mThreadCondition.wait(); + mThreadMutex.unlock(); + Debug( 1, "Started thread %d", mPid ); +} + +void Thread::join() +{ + Debug( 1, "Joining thread %d", mPid ); + if ( isThread() ) + throw ThreadException( "Can't self join thread" ); + mThreadMutex.lock(); + if ( mPid >= 0 ) + { + if ( mStarted ) + { + void *threadStatus = 0; + if ( pthread_join( mThread, &threadStatus ) < 0 ) + throw ThreadException( stringtf( "Can't join sender thread: %s", strerror(errno) ) ); + mStarted = false; + Debug( 1, "Thread %d exited, status %p", mPid, threadStatus ); + } + else + { + Warning( "Attempt to join already finished thread %d", mPid ); + } + } + else + { + Warning( "Attempt to join non-started thread %d", mPid ); + } + mThreadMutex.unlock(); + Debug( 1, "Joined thread %d", mPid ); +} + +void Thread::kill( int signal ) +{ + pthread_kill( mThread, signal ); +} + +// Some explicit template instantiations +#include "zm_threaddata.cpp" diff --git a/src/zm_thread.h b/src/zm_thread.h new file mode 100644 index 000000000..a4ba71edd --- /dev/null +++ b/src/zm_thread.h @@ -0,0 +1,227 @@ +// +// ZoneMinder Thread Class Interface, $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. +// + +#ifndef ZM_THREAD_H +#define ZM_THREAD_H + +#include +#include +#include "zm_exception.h" +#include "zm_utils.h" + +class ThreadException : public Exception +{ +public: + ThreadException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)syscall(224) ) ) + { + } +}; + +class Mutex +{ +friend class Condition; + +private: + pthread_mutex_t mMutex; + +public: + Mutex(); + ~Mutex(); + +private: + pthread_mutex_t *getMutex() + { + return( &mMutex ); + } + +public: + void lock(); + void lock( int secs ); + void lock( double secs ); + void unlock(); + bool locked(); +}; + +class ScopedMutex +{ +private: + Mutex &mMutex; + +public: + ScopedMutex( Mutex &mutex ) : mMutex( mutex ) + { + mMutex.lock(); + } + ~ScopedMutex() + { + mMutex.unlock(); + } + +private: + ScopedMutex( const ScopedMutex & ); +}; + +class Condition +{ +private: + Mutex &mMutex; + pthread_cond_t mCondition; + +public: + Condition( Mutex &mutex ); + ~Condition(); + + void wait(); + bool wait( int secs ); + bool wait( double secs ); + void signal(); + void broadcast(); +}; + +class Semaphore : public Condition +{ +private: + Mutex mMutex; + +public: + Semaphore() : Condition( mMutex ) + { + } + + void wait() + { + mMutex.lock(); + Condition::wait(); + mMutex.unlock(); + } + bool wait( int secs ) + { + mMutex.lock(); + bool result = Condition::wait( secs ); + mMutex.unlock(); + return( result ); + } + bool wait( double secs ) + { + mMutex.lock(); + bool result = Condition::wait( secs ); + mMutex.unlock(); + return( result ); + } + void signal() + { + mMutex.lock(); + Condition::signal(); + mMutex.unlock(); + } + void broadcast() + { + mMutex.lock(); + Condition::broadcast(); + mMutex.unlock(); + } +}; + +template class ThreadData +{ +private: + T mValue; + mutable bool mChanged; + mutable Mutex mMutex; + mutable Condition mCondition; + +public: + __attribute__((used)) ThreadData() : mCondition( mMutex ) + { + } + __attribute__((used)) ThreadData( T value ) : mValue( value ), mCondition( mMutex ) + { + } + //~ThreadData() {} + + __attribute__((used)) operator T() const + { + return( getValue() ); + } + __attribute__((used)) const T operator=( const T value ) + { + return( setValue( value ) ); + } + + __attribute__((used)) const T getValueImmediate() const + { + return( mValue ); + } + __attribute__((used)) T setValueImmediate( const T value ) + { + return( mValue = value ); + } + __attribute__((used)) const T getValue() const; + __attribute__((used)) T setValue( const T value ); + __attribute__((used)) const T getUpdatedValue() const; + __attribute__((used)) const T getUpdatedValue( double secs ) const; + __attribute__((used)) const T getUpdatedValue( int secs ) const; + __attribute__((used)) void updateValueSignal( const T value ); + __attribute__((used)) void updateValueBroadcast( const T value ); +}; + +class Thread +{ +public: + typedef void *(*ThreadFunc)( void * ); + +protected: + pthread_t mThread; + + Mutex mThreadMutex; + Condition mThreadCondition; + pid_t mPid; + bool mStarted; + bool mRunning; + +protected: + Thread(); + virtual ~Thread(); + + pid_t id() const + { + return( (pid_t)syscall(224) ); + } + void exit( int status = 0 ) + { + //INFO( "Exiting" ); + pthread_exit( (void *)&status ); + } + static void *mThreadFunc( void *arg ); + +public: + virtual int run() = 0; + + void start(); + void join(); + void kill( int signal ); + bool isThread() + { + return( mPid > -1 && pthread_equal( pthread_self(), mThread ) ); + } + bool isStarted() const { return( mStarted ); } + bool isRunning() const { return( mRunning ); } +}; + +#endif // ZM_THREAD_H diff --git a/src/zm_threaddata.cpp b/src/zm_threaddata.cpp new file mode 100644 index 000000000..0742063c9 --- /dev/null +++ b/src/zm_threaddata.cpp @@ -0,0 +1,22 @@ +// +// ZoneMinder Explicit Thread Template Class Instantiations, $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. +// + +template class ThreadData; +template class ThreadData; + diff --git a/src/zm_time.cpp b/src/zm_time.cpp new file mode 100644 index 000000000..08b673469 --- /dev/null +++ b/src/zm_time.cpp @@ -0,0 +1,22 @@ +// +// ZoneMinder Time Functions & Definitions Implementation, $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. +// + +#include "zm_time.h" + +// Blank diff --git a/src/zm_time.h b/src/zm_time.h new file mode 100644 index 000000000..646133feb --- /dev/null +++ b/src/zm_time.h @@ -0,0 +1,209 @@ +// +// ZoneMinder Time Functions & Definitions, $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. +// + +#ifndef ZM_TIME_H +#define ZM_TIME_H + +#include "zm.h" + +#include + +// Structure used for storing the results of the subtraction +// of one struct timeval from another + +struct DeltaTimeval +{ + bool positive; + unsigned long delta; + unsigned long sec; + unsigned long fsec; + unsigned long prec; +}; + +#define DT_GRAN_1000000 1000000 +#define DT_PREC_6 DT_GRAN_1000000 +#define DT_GRAN_100000 100000 +#define DT_PREC_5 DT_GRAN_100000 +#define DT_GRAN_10000 10000 +#define DT_PREC_4 DT_GRAN_10000 +#define DT_GRAN_1000 1000 +#define DT_PREC_3 DT_GRAN_1000 +#define DT_GRAN_100 100 +#define DT_PREC_2 DT_GRAN_100 +#define DT_GRAN_10 10 +#define DT_PREC_1 DT_GRAN_10 + +#define DT_MAXGRAN DT_GRAN_1000000 + +// This obviously wouldn't work for massive deltas but as it's mostly +// for frames it will only usually be a fraction of a second or so +#define DELTA_TIMEVAL( result, time1, time2, precision ) \ +{ \ + int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ + result.positive = (delta>=0); \ + result.delta = abs(delta); \ + result.sec = result.delta/(precision); \ + result.fsec = result.delta%(precision); \ + result.prec = (precision); \ +} + +#define TIMEVAL_INTERVAL( result, time1, time2, precision ) \ +{ \ + int delta = (((time1).tv_sec-(time2).tv_sec)*(precision))+(((time1).tv_usec-(time2).tv_usec)/(DT_MAXGRAN/(precision))); \ + result.positive = (delta>=0); \ + result.delta = abs(delta); \ + result.sec = result.delta/(precision); \ + result.fsec = result.delta%(precision); \ + result.prec = (precision); \ +} + +#define USEC_PER_SEC 1000000 +#define MSEC_PER_SEC 1000 + +extern struct timeval tv; +typedef typeof(tv.tv_sec) ast_time_t; +typedef typeof(tv.tv_usec) ast_suseconds_t; + +inline int tvDiffUsec( struct timeval first, struct timeval last ) +{ + return( (last.tv_sec - first.tv_sec) * USEC_PER_SEC) + ((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC ); +} + +inline int tvDiffUsec( struct timeval first ) +{ + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffUsec( first, now ) ); +} + +inline int tvDiffMsec( struct timeval first, struct timeval last ) +{ + return( (last.tv_sec - first.tv_sec) * MSEC_PER_SEC) + (((MSEC_PER_SEC + last.tv_usec - first.tv_usec) / MSEC_PER_SEC) - MSEC_PER_SEC ); +} + +inline int tvDiffMsec( struct timeval first ) +{ + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffMsec( first, now ) ); +} + +inline double tvDiffSec( struct timeval first, struct timeval last ) +{ + return( double(last.tv_sec - first.tv_sec) + double(((USEC_PER_SEC + last.tv_usec - first.tv_usec) - USEC_PER_SEC) / (1.0*USEC_PER_SEC) ) ); +} + +inline double tvDiffSec( struct timeval first ) +{ + struct timeval now; + gettimeofday( &now, NULL ); + return( tvDiffSec( first, now ) ); +} + +inline struct timeval tvZero() +{ + struct timeval t = { 0, 0 }; + return( t ); +} + +inline int tvIsZero( const struct timeval t ) +{ + return( t.tv_sec == 0 && t.tv_usec == 0 ); +} + +inline int tvCmp( struct timeval t1, struct timeval t2 ) +{ + if ( t1.tv_sec < t2.tv_sec ) + return( -1 ); + if ( t1.tv_sec > t2.tv_sec ) + return( 1 ); + if ( t1.tv_usec < t2.tv_usec ) + return( -1 ); + if ( t1.tv_usec > t2.tv_usec ) + return( 1 ); + return( 0 ); +} + +inline int tvEq( struct timeval t1, struct timeval t2 ) +{ + return( t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec ); +} + +inline struct timeval tvNow( void ) +{ + struct timeval t; + gettimeofday( &t, NULL ); + return( t ); +} + +inline struct timeval tvCheck( struct timeval &t ) +{ + if ( t.tv_usec >= USEC_PER_SEC ) + { + Warning( "Timestamp too large %ld.%ld\n", t.tv_sec, (long int) t.tv_usec ); + t.tv_sec += t.tv_usec / USEC_PER_SEC; + t.tv_usec %= USEC_PER_SEC; + } + else if ( t.tv_usec < 0 ) + { + Warning( "Got negative timestamp %ld.%ld\n", t.tv_sec, (long int)t.tv_usec ); + t.tv_usec = 0; + } + return( t ); +} + +// Add t2 to t1 +inline struct timeval tvAdd( struct timeval t1, struct timeval t2 ) +{ + tvCheck(t1); + tvCheck(t2); + t1.tv_sec += t2.tv_sec; + t1.tv_usec += t2.tv_usec; + if ( t1.tv_usec >= USEC_PER_SEC ) + { + t1.tv_sec++; + t1.tv_usec -= USEC_PER_SEC; + } + return( t1 ); +} + +// Subtract t2 from t1 +inline struct timeval tvSub( struct timeval t1, struct timeval t2 ) +{ + tvCheck(t1); + tvCheck(t2); + t1.tv_sec -= t2.tv_sec; + t1.tv_usec -= t2.tv_usec; + if ( t1.tv_usec < 0 ) + { + t1.tv_sec--; + t1.tv_usec += USEC_PER_SEC; + } + return( t1 ) ; +} + +inline struct timeval tvMake( time_t sec, suseconds_t usec ) +{ + struct timeval t; + t.tv_sec = sec; + t.tv_usec = usec; + return( t ); +} + +#endif // ZM_TIME_H diff --git a/src/zm_timer.cpp b/src/zm_timer.cpp new file mode 100644 index 000000000..fbac45435 --- /dev/null +++ b/src/zm_timer.cpp @@ -0,0 +1,119 @@ +// +// ZoneMinder Timer Class Implementation, $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. +// + +#include "zm_timer.h" + +#include "zm_logger.h" + +int Timer::TimerThread::mNextTimerId = 0; + +Timer::TimerThread::TimerThread( Timer &timer, int duration, bool repeat ) : + mTimerId( 0 ), + mTimer( timer ), + mDuration( duration ), + mRepeat( repeat ), + mReset( false ), + mExpiryFlag( true ) +{ + mAccessMutex.lock(); + mTimerId = mNextTimerId++; + Debug( 5, "Creating timer %d for %d seconds%s", mTimerId, mDuration, mRepeat?", repeating":"" ); + mAccessMutex.unlock(); +} + +Timer::TimerThread::~TimerThread() +{ + cancel(); +} + +void Timer::TimerThread::cancel() +{ + mAccessMutex.lock(); + if ( mRunning ) + { + Debug( 4, "Cancelling timer %d", mTimerId ); + mRepeat = false; + mReset = false; + mExpiryFlag.updateValueSignal( false ); + } + mAccessMutex.unlock(); +} + +void Timer::TimerThread::reset() +{ + mAccessMutex.lock(); + if ( mRunning ) + { + Debug( 4, "Resetting timer" ); + mReset = true; + mExpiryFlag.updateValueSignal( false ); + } + else + { + Error( "Attempting to reset expired timer %d", mTimerId ); + } + mAccessMutex.unlock(); +} + +int Timer::TimerThread::run() +{ + Debug( 4, "Starting timer %d for %d seconds", mTimerId, mDuration ); + bool timerExpired = false; + do + { + mAccessMutex.lock(); + mReset = false; + mExpiryFlag.setValue( true ); + mAccessMutex.unlock(); + timerExpired = mExpiryFlag.getUpdatedValue( mDuration ); + mAccessMutex.lock(); + if ( timerExpired ) + { + Debug( 4, "Timer %d expired", mTimerId ); + mTimer.expire(); + } + else + { + Debug( 4, "Timer %d %s", mTimerId, mReset?"reset":"cancelled" ); + } + mAccessMutex.unlock(); + } while ( mRepeat || (mReset && !timerExpired) ); + return( timerExpired ); +} + +Timer::Timer( int timeout, bool repeat ) : mTimerThread( *this, timeout, repeat ) +{ + mTimerThread.start(); +} + +Timer::~Timer() +{ + //cancel(); +} + +void Timer::Timer::cancel() +{ + mTimerThread.cancel(); +} + +void Timer::Timer::reset() +{ + mTimerThread.reset(); +} + diff --git a/src/zm_timer.h b/src/zm_timer.h new file mode 100644 index 000000000..f1aa54706 --- /dev/null +++ b/src/zm_timer.h @@ -0,0 +1,87 @@ +// +// ZoneMinder Timer Class Interface, $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. +// + +#ifndef ZM_TIMER_H +#define ZM_TIMER_H + +#include "zm_thread.h" + +#include "zm_exception.h" + +class Timer +{ +private: + class TimerException : public Exception + { + public: + TimerException( const std::string &message ) : Exception( stringtf( "(%d) "+message, (long int)syscall(224) ) ) + { + } + }; + + class TimerThread : public Thread + { + private: + typedef ThreadData ExpiryFlag; + + private: + static int mNextTimerId; + + private: + int mTimerId; + Timer &mTimer; + int mDuration; + int mRepeat; + int mReset; + ExpiryFlag mExpiryFlag; + Mutex mAccessMutex; + + private: + void quit() + { + cancel(); + } + + public: + TimerThread( Timer &timer, int timeout, bool repeat ); + ~TimerThread(); + + void cancel(); + void reset(); + int run(); + }; + +protected: + TimerThread mTimerThread; + +protected: + Timer( int timeout, bool repeat=false ); + +public: + virtual ~Timer(); + +protected: + virtual void expire()=0; + +public: + void cancel(); + void reset(); +}; + +#endif // ZM_TIMER_H diff --git a/src/zm_user.cpp b/src/zm_user.cpp new file mode 100644 index 000000000..9bc712230 --- /dev/null +++ b/src/zm_user.cpp @@ -0,0 +1,246 @@ +/* + * ZoneMinder regular expression class implementation, $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. +*/ + +#include "zm.h" +#include "zm_db.h" + +#include "zm_user.h" + +#include +#include +#include +#include + +User::User() +{ + username[0] = password[0] = 0; + enabled = false; + stream = events = control = monitors = system = PERM_NONE; + monitor_ids = 0; +} + +User::User( MYSQL_ROW &dbrow ) +{ + int index = 0; + strncpy( username, dbrow[index++], sizeof(username) ); + strncpy( password, dbrow[index++], sizeof(password) ); + enabled = (bool)atoi( dbrow[index++] ); + stream = (Permission)atoi( dbrow[index++] ); + events = (Permission)atoi( dbrow[index++] ); + control = (Permission)atoi( dbrow[index++] ); + monitors = (Permission)atoi( dbrow[index++] ); + system = (Permission)atoi( dbrow[index++] ); + monitor_ids = 0; + char *monitor_ids_str = dbrow[index++]; + if ( monitor_ids_str && *monitor_ids_str ) + { + monitor_ids = new int[strlen(monitor_ids_str)]; + int n_monitor_ids = 0; + const char *ptr = monitor_ids_str; + do + { + int id = 0; + while( isdigit( *ptr ) ) + { + id *= 10; + id += *ptr-'0'; + ptr++; + } + if ( id ) + { + monitor_ids[n_monitor_ids++] = id; + if ( !*ptr ) + break; + } + while ( !isdigit( *ptr ) ) + ptr++; + } while( *ptr ); + monitor_ids[n_monitor_ids] = 0; + } +} + +User::~User() +{ + delete monitor_ids; +} + +bool User::canAccess( int monitor_id ) +{ + if ( !monitor_ids ) + { + return( true ); + } + for ( int i = 0; monitor_ids[i]; i++ ) + { + if ( monitor_ids[i] == monitor_id ) + { + return( true ); + } + } + return( false ); +} + +// Function to load a user from username and password +User *zmLoadUser( const char *username, const char *password ) +{ + char sql[ZM_SQL_SML_BUFSIZ] = ""; + + if ( password ) + { + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Password = password('%s') and Enabled = 1", username, password ); + } + else + { + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Username = '%s' and Enabled = 1", username ); + } + + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_users = mysql_num_rows( result ); + + if ( n_users != 1 ) + { + Warning( "Unable to authenticate user %s", username ); + return( 0 ); + } + + MYSQL_ROW dbrow = mysql_fetch_row( result ); + + User *user = new User( dbrow ); + Info( "Authenticated user '%s'", user->getUsername() ); + + mysql_free_result( result ); + + return( user ); +} + +// Function to validate an authentication string +User *zmLoadAuthUser( const char *auth, bool use_remote_addr ) +{ +#if HAVE_DECL_MD5 || HAVE_DECL_GNUTLS_FINGERPRINT +#ifdef HAVE_GCRYPT_H + // Special initialisation for libgcrypt + if ( !gcry_check_version( GCRYPT_VERSION ) ) + { + Fatal( "Unable to initialise libgcrypt" ); + } + gcry_control( GCRYCTL_DISABLE_SECMEM, 0 ); + gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 ); +#endif // HAVE_GCRYPT_H + + const char *remote_addr = ""; + if ( use_remote_addr ) + { + remote_addr = getenv( "REMOTE_ADDR" ); + if ( !remote_addr ) + { + Warning( "Can't determine remote address, using null" ); + remote_addr = ""; + } + } + + Debug( 1, "Attempting to authenticate user from auth string '%s'", auth ); + char sql[ZM_SQL_SML_BUFSIZ] = ""; + snprintf( sql, sizeof(sql), "select Username, Password, Enabled, Stream+0, Events+0, Control+0, Monitors+0, System+0, MonitorIds from Users where Enabled = 1" ); + + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_users = mysql_num_rows( result ); + + if ( n_users < 1 ) + { + Warning( "Unable to authenticate user" ); + return( 0 ); + } + + while( MYSQL_ROW dbrow = mysql_fetch_row( result ) ) + { + const char *user = dbrow[0]; + const char *pass = dbrow[1]; + + char auth_key[512] = ""; + char auth_md5[32+1] = ""; + size_t md5len = 32; + unsigned char md5sum[md5len]; + + time_t now = time( 0 ); + int max_tries = 2; + + for ( int i = 0; i < max_tries; i++, now -= (60*60) ) + { + struct tm *now_tm = localtime( &now ); + + snprintf( auth_key, sizeof(auth_key), "%s%s%s%s%d%d%d%d", + config.auth_hash_secret, + user, + pass, + remote_addr, + now_tm->tm_hour, + now_tm->tm_mday, + now_tm->tm_mon, + now_tm->tm_year + ); + +#if HAVE_DECL_MD + MD5( (unsigned char *)auth_key, strlen(auth_key), md5sum ); +#elif HAVE_DECL_GNUTLS_FINGERPRINT + gnutls_datum_t md5data = { (unsigned char *)auth_key, strlen(auth_key) }; + gnutls_fingerprint( GNUTLS_DIG_MD5, &md5data, md5sum, &md5len ); +#endif + auth_md5[0] = '\0'; + for ( unsigned int j = 0; j < md5len; j++ ) + { + sprintf( &auth_md5[2*j], "%02x", md5sum[j] ); + } + Debug( 1, "Checking auth_key '%s' -> auth_md5 '%s'", auth_key, auth_md5 ); + + if ( !strcmp( auth, auth_md5 ) ) + { + // We have a match + User *user = new User( dbrow ); + Info( "Authenticated user '%s'", user->getUsername() ); + return( user ); + } + } + } +#else // HAVE_DECL_MD5 + Error( "You need to build with gnutls or openssl installed to use hash based authentication" ); +#endif // HAVE_DECL_MD5 + return( 0 ); +} diff --git a/src/zm_user.h b/src/zm_user.h new file mode 100644 index 000000000..95fb71474 --- /dev/null +++ b/src/zm_user.h @@ -0,0 +1,74 @@ +/* + * ZoneMinder User Class Interface, $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. +*/ + +#include "zm.h" +#include "zm_db.h" + +#ifndef ZM_USER_H +#define ZM_USER_H + +#if HAVE_GNUTLS_OPENSSL_H +#include +#endif +#if HAVE_GNUTLS_GNUTLS_H +#include +#endif + +#if HAVE_GCRYPT_H +#include +#elif HAVE_LIBCRYPTO +#include +#endif // HAVE_L || HAVE_LIBCRYPTO + +class User +{ +public: + typedef enum { PERM_NONE=1, PERM_VIEW, PERM_EDIT } Permission; + +protected: + char username[32+1]; + char password[64+1]; + bool enabled; + Permission stream; + Permission events; + Permission control; + Permission monitors; + Permission system; + int *monitor_ids; + +public: + User(); + User( MYSQL_ROW &dbrow ); + ~User(); + + const char *getUsername() const { return( username ); } + const char *getPassword() const { return( password ); } + bool isEnabled() const { return( enabled ); } + Permission getStream() const { return( stream ); } + Permission getEvents() const { return( events ); } + Permission getControl() const { return( control ); } + Permission getMonitors() const { return( monitors ); } + Permission getSystem() const { return( system ); } + bool canAccess( int monitor_id ); +}; + +User *zmLoadUser( const char *username, const char *password=0 ); +User *zmLoadAuthUser( const char *auth, bool use_remote_addr ); + +#endif // ZM_USER_H diff --git a/src/zm_utils.cpp b/src/zm_utils.cpp new file mode 100644 index 000000000..cef91366e --- /dev/null +++ b/src/zm_utils.cpp @@ -0,0 +1,253 @@ +// +// ZoneMinder General Utility Functions, $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. +// + +//#include "zm_logger.h" +#include "zm.h" +#include "zm_utils.h" + +#include +#include +#include + +unsigned int sseversion = 0; + +const std::string stringtf( const char *format, ... ) +{ + va_list ap; + char tempBuffer[8192]; + std::string tempString; + + va_start(ap, format ); + vsnprintf( tempBuffer, sizeof(tempBuffer), format , ap ); + va_end(ap); + + tempString = tempBuffer; + + return( tempString ); +} + +const std::string stringtf( const std::string &format, ... ) +{ + va_list ap; + char tempBuffer[8192]; + std::string tempString; + + va_start(ap, format ); + vsnprintf( tempBuffer, sizeof(tempBuffer), format.c_str() , ap ); + va_end(ap); + + tempString = tempBuffer; + + return( tempString ); +} + +bool startsWith( const std::string &haystack, const std::string &needle ) +{ + return( haystack.substr( 0, needle.length() ) == needle ); +} + +StringVector split( const std::string &string, const std::string chars, int limit ) +{ + StringVector stringVector; + std::string tempString = string; + std::string::size_type startIndex = 0; + std::string::size_type endIndex = 0; + + //Info( "Looking for '%s' in '%s', limit %d", chars.c_str(), string.c_str(), limit ); + do + { + // Find delimiters + endIndex = string.find_first_of( chars, startIndex ); + //Info( "Got endIndex at %d", endIndex ); + if ( endIndex > 0 ) + { + //Info( "Adding '%s'", string.substr( startIndex, endIndex-startIndex ).c_str() ); + stringVector.push_back( string.substr( startIndex, endIndex-startIndex ) ); + } + if ( endIndex == std::string::npos ) + break; + // Find non-delimiters + startIndex = tempString.find_first_not_of( chars, endIndex ); + if ( limit && (stringVector.size() == (unsigned int)(limit-1)) ) + { + stringVector.push_back( string.substr( startIndex ) ); + break; + } + //Info( "Got new startIndex at %d", startIndex ); + } while ( startIndex != std::string::npos ); + //Info( "Finished with %d strings", stringVector.size() ); + + return( stringVector ); +} + +const std::string base64Encode( const std::string &inString ) +{ + static char base64_table[64] = { '\0' }; + + if ( !base64_table[0] ) + { + int i = 0; + for ( char c = 'A'; c <= 'Z'; c++ ) + base64_table[i++] = c; + for ( char c = 'a'; c <= 'z'; c++ ) + base64_table[i++] = c; + for ( char c = '0'; c <= '9'; c++ ) + base64_table[i++] = c; + base64_table[i++] = '+'; + base64_table[i++] = '/'; + } + + std::string outString; + outString.reserve( 2 * inString.size() ); + + const char *inPtr = inString.c_str(); + while( *inPtr ) + { + unsigned char selection = *inPtr >> 2; + unsigned char remainder = (*inPtr++ & 0x03) << 4; + outString += base64_table[selection]; + + if ( *inPtr ) + { + selection = remainder | (*inPtr >> 4); + remainder = (*inPtr++ & 0x0f) << 2; + outString += base64_table[selection]; + + if ( *inPtr ) + { + selection = remainder | (*inPtr >> 6); + outString += base64_table[selection]; + selection = (*inPtr++ & 0x3f); + outString += base64_table[selection]; + } + else + { + outString += base64_table[remainder]; + outString += '='; + } + } + else + { + outString += base64_table[remainder]; + outString += '='; + outString += '='; + } + } + return( outString ); +} + +/* Sets sse_version */ +void ssedetect() { +#if (defined(__i386__) || defined(__x86_64__)) + /* x86 or x86-64 processor */ + uint32_t r_edx, r_ecx; + + __asm__ __volatile__( + "mov $0x1,%%eax\n\t" + "cpuid\n\t" + : "=d" (r_edx), "=c" (r_ecx) + : + : "%eax", "%ebx" + ); + + if (r_ecx & 0x00000200) { + sseversion = 35; /* SSSE3 */ + Debug(1,"Detected a x86\\x86-64 processor with SSSE3"); + } else if (r_ecx & 0x00000001) { + sseversion = 30; /* SSE3 */ + Debug(1,"Detected a x86\\x86-64 processor with SSE3"); + } else if (r_edx & 0x04000000) { + sseversion = 20; /* SSE2 */ + Debug(1,"Detected a x86\\x86-64 processor with SSE2"); + } else if (r_edx & 0x02000000) { + sseversion = 10; /* SSE */ + Debug(1,"Detected a x86\\x86-64 processor with SSE"); + } else { + sseversion = 0; + Debug(1,"Detected a x86\\x86-64 processor"); + } + +#else + /* Non x86 or x86-64 processor, SSE2 is not available */ + Debug(1,"Detected a non x86\\x86-64 processor"); + sseversion = 0; +#endif +} + +/* SSE2 aligned memory copy. Useful for big copying of aligned memory like image buffers in ZM */ +/* For platforms without SSE2 we will use standard x86 asm memcpy or glibc's memcpy() */ +__attribute__((noinline,__target__("sse2"))) void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes) { +#if ((defined(__i386__) || defined(__x86_64__) || defined(ZM_KEEP_SSE)) && !defined(ZM_STRIP_SSE)) + if(bytes > 128) { + unsigned int remainder = bytes % 128; + const uint8_t* lastsrc = (uint8_t*)src + (bytes - remainder); + + __asm__ __volatile__( + "sse2_copy_iter:\n\t" + "movdqa (%0),%%xmm0\n\t" + "movdqa 0x10(%0),%%xmm1\n\t" + "movdqa 0x20(%0),%%xmm2\n\t" + "movdqa 0x30(%0),%%xmm3\n\t" + "movdqa 0x40(%0),%%xmm4\n\t" + "movdqa 0x50(%0),%%xmm5\n\t" + "movdqa 0x60(%0),%%xmm6\n\t" + "movdqa 0x70(%0),%%xmm7\n\t" + "movntdq %%xmm0,(%1)\n\t" + "movntdq %%xmm1,0x10(%1)\n\t" + "movntdq %%xmm2,0x20(%1)\n\t" + "movntdq %%xmm3,0x30(%1)\n\t" + "movntdq %%xmm4,0x40(%1)\n\t" + "movntdq %%xmm5,0x50(%1)\n\t" + "movntdq %%xmm6,0x60(%1)\n\t" + "movntdq %%xmm7,0x70(%1)\n\t" + "add $0x80, %0\n\t" + "add $0x80, %1\n\t" + "cmp %2, %0\n\t" + "jb sse2_copy_iter\n\t" + "test %3, %3\n\t" + "jz sse2_copy_finish\n\t" + "cld\n\t" + "rep movsb\n\t" + "sse2_copy_finish:\n\t" + : + : "S" (src), "D" (dest), "r" (lastsrc), "c" (remainder) + : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", "cc", "memory" + ); + + } else { + /* Standard memcpy */ + __asm__ __volatile__("cld; rep movsb" :: "S"(src), "D"(dest), "c"(bytes) : "cc", "memory"); + } +#else + /* Non x86\x86-64 platform, use memcpy */ + memcpy(dest,src,bytes); +#endif + return dest; +} + +void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff) { + if (((end->tv_nsec)-(start->tv_nsec))<0) { + diff->tv_sec = end->tv_sec-start->tv_sec-1; + diff->tv_nsec = 1000000000+end->tv_nsec-start->tv_nsec; + } else { + diff->tv_sec = end->tv_sec-start->tv_sec; + diff->tv_nsec = end->tv_nsec-start->tv_nsec; + } +} + diff --git a/src/zm_utils.h b/src/zm_utils.h new file mode 100644 index 000000000..658c10180 --- /dev/null +++ b/src/zm_utils.h @@ -0,0 +1,54 @@ +// +// ZoneMinder General Utility Functions, $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. +// + +#ifndef ZM_UTILS_H +#define ZM_UTILS_H + +#include +#include +#include +#include + +typedef std::vector StringVector; + +const std::string stringtf( const char *format, ... ); +const std::string stringtf( const std::string &format, ... ); + +bool startsWith( const std::string &haystack, const std::string &needle ); +StringVector split( const std::string &string, const std::string chars, int limit=0 ); + +const std::string base64Encode( const std::string &inString ); + +inline int max( int a, int b ) +{ + return( a>=b?a:b ); +} + +inline int min( int a, int b ) +{ + return( a<=b?a:b ); +} + +void ssedetect(); +void* sse2_aligned_memcpy(void* dest, const void* src, size_t bytes); +void timespec_diff(struct timespec *start, struct timespec *end, struct timespec *diff); + +extern unsigned int sseversion; + +#endif // ZM_UTILS_H diff --git a/src/zm_zone.cpp b/src/zm_zone.cpp new file mode 100644 index 000000000..1319607fa --- /dev/null +++ b/src/zm_zone.cpp @@ -0,0 +1,1082 @@ +// +// ZoneMinder Zone Class Implementation, $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. +// + +#include "zm.h" +#include "zm_db.h" +#include "zm_zone.h" +#include "zm_image.h" +#include "zm_monitor.h" + +void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames ) +{ + monitor = p_monitor; + + id = p_id; + label = new char[strlen(p_label)+1]; + strcpy( label, p_label ); + type = p_type; + polygon = p_polygon; + alarm_rgb = p_alarm_rgb; + check_method = p_check_method; + min_pixel_threshold = p_min_pixel_threshold; + max_pixel_threshold = p_max_pixel_threshold; + min_alarm_pixels = p_min_alarm_pixels; + max_alarm_pixels = p_max_alarm_pixels; + filter_box = p_filter_box; + min_filter_pixels = p_min_filter_pixels; + max_filter_pixels = p_max_filter_pixels; + min_blob_pixels = p_min_blob_pixels; + max_blob_pixels = p_max_blob_pixels; + min_blobs = p_min_blobs; + max_blobs = p_max_blobs; + overload_frames = p_overload_frames; + + Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames ); + + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + image = 0; + score = 0; + + overload_count = 0; + + pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); + pg_image->Clear(); + pg_image->Fill( 0xff, polygon ); + pg_image->Outline( 0xff, polygon ); + + ranges = new Range[monitor->Height()]; + for ( unsigned int y = 0; y < monitor->Height(); y++) + { + ranges[y].lo_x = -1; + ranges[y].hi_x = 0; + ranges[y].off_x = 0; + const uint8_t *ppoly = pg_image->Buffer( 0, y ); + for ( unsigned int x = 0; x < monitor->Width(); x++, ppoly++ ) + { + if ( *ppoly ) + { + if ( ranges[y].lo_x == -1 ) + { + ranges[y].lo_x = x; + } + if ( (unsigned int)ranges[y].hi_x < x ) + { + ranges[y].hi_x = x; + } + } + } + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id); + } + pg_image->WriteJpeg( diag_path ); + } +} + +Zone::~Zone() +{ + delete[] label; + delete image; + delete pg_image; + delete[] ranges; +} + +void Zone::RecordStats( const Event *event ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event stats: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + + +//============================================================================= +bool Zone::CheckOverloadCount() +{ + Info("Overloaded count: %d, Overloaded frames: %d", overload_count, overload_frames); + if ( overload_count ) + { + Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + overload_count--; + return( false ); + } + return true; +} + +void Zone::SetScore(unsigned int nScore) +{ + score = nScore; +} + + +void Zone::SetAlarmImage(const Image* srcImage) +{ + delete image; + image = new Image(*srcImage); +} + +int Zone::GetOverloadCount() +{ + return overload_count; +} + +void Zone::SetOverloadCount(int nOverCount) +{ + overload_count = nOverCount; +} + +int Zone::GetOverloadFrames() +{ + return overload_frames; +} +//=========================================================================== + + + +bool Zone::CheckAlarms( const Image *delta_image ) +{ + //bool alarm = false; // nextime + + ResetStats(); + + if ( overload_count ) + { + Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + overload_count--; + return( false ); + } + + delete image; + // Get the difference image + Image *diff_image = image = new Image( *delta_image ); + int diff_width = diff_image->Width(); + uint8_t* diff_buff = (uint8_t*)diff_image->Buffer(); + uint8_t* pdiff; + const uint8_t* ppoly; + + unsigned int pixel_diff_count = 0; + + int alarm_lo_x = 0; + int alarm_hi_x = 0; + int alarm_lo_y = 0; + int alarm_hi_y = 0; + + int alarm_mid_x = -1; + int alarm_mid_y = -1; + + unsigned int lo_y = polygon.LoY(); + unsigned int lo_x = polygon.LoX(); + unsigned int hi_x = polygon.HiX(); + unsigned int hi_y = polygon.HiY(); + + Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ); + + + Debug( 5, "Checking for alarmed pixels" ); + /* if(config.cpu_extensions && sseversion >= 20) { + sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } else { + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } */ + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 ); + } + diff_image->WriteJpeg( diag_path ); + } + + if ( pixel_diff_count && alarm_pixels ) + pixel_diff = pixel_diff_count/alarm_pixels; + Debug( 5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff ); + + if( alarm_pixels ) { + if( min_alarm_pixels && (alarm_pixels < (unsigned int)min_alarm_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_alarm_pixels && (alarm_pixels > (unsigned int)max_alarm_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No alarmed pixels */ + return (false); + } + + score = (100*alarm_pixels)/polygon.Area(); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + if ( check_method >= FILTERED_PIXELS ) + { + int bx = filter_box.X(); + int by = filter_box.Y(); + int bx1 = bx-1; + int by1 = by-1; + + Debug( 5, "Checking for filtered pixels" ); + if ( bx > 1 || by > 1 ) + { + // Now remove any pixels smaller than our filter size + unsigned char *cpdiff; + int ldx, hdx, ldy, hdy; + bool block; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; + + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + // Check participation in an X block + ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; + hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); + ldy = (y>=(lo_y+by1))?-by1:lo_y-y; + hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); + block = false; + for ( int dy = ldy; !block && dy <= hdy; dy++ ) + { + for ( int dx = ldx; !block && dx <= hdx; dx++ ) + { + block = true; + for ( int dy2 = 0; block && dy2 < by; dy2++ ) + { + for ( int dx2 = 0; block && dx2 < bx; dx2++ ) + { + cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2)); + if ( !*cpdiff ) + { + block = false; + } + } + } + } + } + if ( !block ) + { + *pdiff = BLACK; + continue; + } + alarm_filter_pixels++; + } + } + } + } + else + { + alarm_filter_pixels = alarm_pixels; + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 ); + } + diff_image->WriteJpeg( diag_path ); + } + + Debug( 5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels ); + + if( alarm_filter_pixels ) { + if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No filtered pixels */ + return (false); + } + + score = (100*alarm_filter_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + if ( check_method >= BLOBS ) + { + Debug( 5, "Checking for blob pixels" ); + typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; + BlobStats blob_stats[256]; + memset( blob_stats, 0, sizeof(BlobStats)*256 ); + uint8_t *spdiff; + uint8_t last_x, last_y; + BlobStats *bsx, *bsy; + BlobStats *bsm, *bss; + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; + + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff ); + //last_x = (x>lo_x)?*(pdiff-1):0; + //last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0; + + last_x = 0; + if(x > 0) { + if((x-1) >= lo_x) { + last_x = *(pdiff-1); + } + } + + last_y = 0; + if(y > 0) { + if((y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x) { + last_y = *(pdiff-diff_width); + } + } + + if ( last_x ) + { + Debug( 9, "Left neighbour is %d", last_x ); + bsx = &blob_stats[last_x]; + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + bsy = &blob_stats[last_y]; + if ( last_x == last_y ) + { + Debug( 9, "Matching neighbours, setting to %d", last_x ); + // Add to the blob from the x side (either side really) + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( (int)y > bsx->hi_y ) bsx->hi_y = y; + } + else + { + // Aggregate blobs + bsm = bsx->count>=bsy->count?bsx:bsy; + bss = bsm==bsx?bsy:bsx; + + Debug( 9, "Different neighbours, setting pixels of %d to %d", bss->tag, bsm->tag ); + Debug( 9, "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + // Now change all those pixels to the other setting + int changed = 0; + for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) + { + int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x; + int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x; + + Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx ); + Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x ); + spdiff = diff_buff + ((diff_width * sy) + lo_sx); + for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) + { + Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff ); + if ( *spdiff == bss->tag ) + { + Debug( 9, "Setting pixel" ); + *spdiff = bsm->tag; + changed++; + } + } + } + *pdiff = bsm->tag; + alarm_blob_pixels++; + if ( !changed ) + { + Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + Error( "No pixels changed, exiting" ); + exit( -1 ); + } + + // Merge the slave blob into the master + bsm->count += bss->count+1; + if ( x > bsm->hi_x ) bsm->hi_x = x; + if ( (int)y > bsm->hi_y ) bsm->hi_y = y; + if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x; + if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y; + if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x; + if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y; + + alarm_blobs--; + + Debug( 6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs ); + + // Clear out the old blob + bss->tag = 0; + bss->count = 0; + bss->lo_x = 0; + bss->lo_y = 0; + bss->hi_x = 0; + bss->hi_y = 0; + } + } + else + { + Debug( 9, "Setting to left neighbour %d", last_x ); + // Add to the blob from the x side + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( (int)y > bsx->hi_y ) bsx->hi_y = y; + } + } + else + { + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + Debug( 9, "Setting to top neighbour %d", last_y ); + + // Add to the blob from the y side + BlobStats *bsy = &blob_stats[last_y]; + + *pdiff = last_y; + alarm_blob_pixels++; + bsy->count++; + if ( x > bsy->hi_x ) bsy->hi_x = x; + if ( (int)y > bsy->hi_y ) bsy->hi_y = y; + } + else + { + // Create a new blob + int i; + for ( i = (WHITE-1); i > 0; i-- ) + { + BlobStats *bs = &blob_stats[i]; + // See if we can recycle one first, only if it's at least two rows up + if ( bs->count && bs->hi_y < (int)(y-1) ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + } + if ( !bs->count ) + { + Debug( 9, "Creating new blob %d", i ); + *pdiff = i; + alarm_blob_pixels++; + bs->tag = i; + bs->count++; + bs->lo_x = bs->hi_x = x; + bs->lo_y = bs->hi_y = y; + alarm_blobs++; + + Debug( 6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs ); + break; + } + } + if ( i == 0 ) + { + Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." ); + x = hi_x+1; + y = hi_y+1; + } + } + } + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 ); + } + diff_image->WriteJpeg( diag_path ); + } + + if ( !alarm_blobs ) + { + return( false ); + } + + Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + + // Now eliminate blobs under the threshold + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + else + { + Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count; + if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count; + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 ); + } + diff_image->WriteJpeg( diag_path ); + } + Debug( 5, "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + + if( alarm_blobs ) { + if( min_blobs && (alarm_blobs < min_blobs) ) { + /* Not enough pixels alarmed */ + return (false); + } else if(max_blobs && (alarm_blobs > max_blobs) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No blobs */ + return (false); + } + + score = (100*alarm_blob_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + alarm_lo_x = polygon.HiX()+1; + alarm_hi_x = polygon.LoX()-1; + alarm_lo_y = polygon.HiY()+1; + alarm_hi_y = polygon.LoY()-1; + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( bs->count == max_blob_size ) + { + if ( config.weighted_alarm_centres ) + { + unsigned long x_total = 0; + unsigned long y_total = 0; + + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + x_total += sx; + y_total += sy; + } + } + } + alarm_mid_x = int(round(x_total/bs->count)); + alarm_mid_y = int(round(y_total/bs->count)); + } + else + { + alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2); + alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2); + } + } + + if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x; + if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; + if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; + if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; + } + } + } + else + { + alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2); + alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2); + } + } + + if ( type == INCLUSIVE ) + { + // score >>= 1; + score /= 2; + } + else if ( type == EXCLUSIVE ) + { + // score <<= 1; + score *= 2; + + } + + Debug( 5, "Adjusted score is %d", score ); + + // Now outline the changed region + if ( score ) + { + //alarm = true; + + alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); + + //if ( monitor->followMotion() ) + if ( true ) + { + alarm_centre = Coord( alarm_mid_x, alarm_mid_y ); + } + else + { + alarm_centre = alarm_box.Centre(); + } + + if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) + { + + // First mask out anything we don't want + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + pdiff = diff_buff + ((diff_width * y) + lo_x); + + int lo_x2 = ranges[y].lo_x; + int hi_x2 = ranges[y].hi_x; + + int lo_gap = lo_x2-lo_x; + if ( lo_gap > 0 ) + { + if ( lo_gap == 1 ) + { + *pdiff++ = BLACK; + } + else + { + memset( pdiff, BLACK, lo_gap ); + pdiff += lo_gap; + } + } + + ppoly = pg_image->Buffer( lo_x2, y ); + for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) + { + if ( !*ppoly ) + { + *pdiff = BLACK; + } + } + + int hi_gap = hi_x-hi_x2; + if ( hi_gap > 0 ) + { + if ( hi_gap == 1 ) + { + *pdiff = BLACK; + } + else + { + memset( pdiff, BLACK, hi_gap ); + } + } + } + + if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { + image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); + } else { + image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); + } + + // Only need to delete this when 'image' becomes detached and points somewhere else + delete diff_image; + } + else + { + delete image; + image = 0; + } + + Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score ); + } + return( true ); +} + +bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) +{ + Debug( 3, "Parsing polygon string '%s'", poly_string ); + + char *str_ptr = new char[strlen(poly_string)+1]; + char *str = str_ptr; + strcpy( str, poly_string ); + + char *ws; + int n_coords = 0; + int max_n_coords = strlen(str)/4; + Coord *coords = new Coord[max_n_coords]; + while( true ) + { + if ( *str == '\0' ) + { + break; + } + ws = strchr( str, ' ' ); + if ( ws ) + { + *ws = '\0'; + } + char *cp = strchr( str, ',' ); + if ( !cp ) + { + Error( "Bogus coordinate %s found in polygon string", str ); + delete[] coords; + delete[] str_ptr; + return( false ); + } + else + { + *cp = '\0'; + char *xp = str; + char *yp = cp+1; + + int x = atoi(xp); + int y = atoi(yp); + + Debug( 3, "Got coordinate %d,%d from polygon string", x, y ); +#if 0 + if ( x < 0 ) + x = 0; + else if ( x >= width ) + x = width-1; + if ( y < 0 ) + y = 0; + else if ( y >= height ) + y = height-1; +#endif + coords[n_coords++] = Coord( x, y ); + } + if ( ws ) + str = ws+1; + else + break; + } + polygon = Polygon( n_coords, coords ); + + Debug( 3, "Successfully parsed polygon string" ); + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + + delete[] coords; + delete[] str_ptr; + + return( true ); +} + +bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) +{ + Debug( 3, "Parsing zone string '%s'", zone_string ); + + char *str_ptr = new char[strlen(zone_string)+1]; + char *str = str_ptr; + strcpy( str, zone_string ); + + char *ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No initial whitespace found in zone string '%s', finishing", str ); + } + zone_id = strtol( str, 0, 10 ); + Debug( 3, "Got zone %d from zone string", zone_id ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } + + *ws = '\0'; + str = ws+1; + + ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string ); + } + colour = strtol( str, 0, 16 ); + Debug( 3, "Got colour %06x from zone string", colour ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } + *ws = '\0'; + str = ws+1; + + bool result = ParsePolygonString( str, polygon ); + + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + + delete[] str_ptr; + + return( result ); +} + +int Zone::Load( Monitor *monitor, Zone **&zones ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,NumCoords,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames from Zones where MonitorId = %d order by Type, Id", monitor->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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_zones = mysql_num_rows( result ); + Debug( 1, "Got %d zones for monitor %s", n_zones, monitor->Name() ); + delete[] zones; + zones = new Zone *[n_zones]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int Id = atoi(dbrow[col++]); + const char *Name = dbrow[col++]; + int Type = atoi(dbrow[col++]); + const char *Units = dbrow[col++]; + /* int NumCoords = */ atoi(dbrow[col++]); + const char *Coords = dbrow[col++]; + int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++; + int CheckMethod = atoi(dbrow[col++]); + int MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterX = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterY = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int OverloadFrames = dbrow[col]?atoi(dbrow[col]):0; col++; + + /* HTML colour code is actually BGR in memory, we want RGB */ + AlarmRGB = rgb_convert(AlarmRGB, ZM_SUBPIX_ORDER_BGR); + + Debug( 5, "Parsing polygon %s", Coords ); + Polygon polygon; + if ( !ParsePolygonString( Coords, polygon ) ) + Panic( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s", Coords, Id, Name, monitor->Name() ); + + if ( polygon.LoX() < 0 || polygon.HiX() >= (int)monitor->Width() + || polygon.LoY() < 0 || polygon.HiY() >= (int)monitor->Height() ) + Panic( "Zone %d/%s for monitor %s extends outside of image dimensions, %d, %d, %d, %d", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() ); + + if ( false && !strcmp( Units, "Percent" ) ) + { + MinAlarmPixels = (MinAlarmPixels*polygon.Area())/100; + MaxAlarmPixels = (MaxAlarmPixels*polygon.Area())/100; + MinFilterPixels = (MinFilterPixels*polygon.Area())/100; + MaxFilterPixels = (MaxFilterPixels*polygon.Area())/100; + MinBlobPixels = (MinBlobPixels*polygon.Area())/100; + MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100; + } + + if ( atoi(dbrow[2]) == Zone::INACTIVE ) + { + zones[i] = new Zone( monitor, Id, Name, polygon ); + } + else + { + zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames ); + } + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + return( n_zones ); +} + +bool Zone::DumpSettings( char *output, bool /*verbose*/ ) +{ + output[0] = 0; + + sprintf( output+strlen(output), " Id : %d\n", id ); + sprintf( output+strlen(output), " Label : %s\n", label ); + sprintf( output+strlen(output), " Type: %d - %s\n", type, + type==ACTIVE?"Active":( + type==INCLUSIVE?"Inclusive":( + type==EXCLUSIVE?"Exclusive":( + type==PRECLUSIVE?"Preclusive":( + type==INACTIVE?"Inactive":"Unknown" + ))))); + sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); + for ( int i = 0; i < polygon.getNumCoords(); i++ ) + { + sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() ); + } + sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb ); + sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method, + check_method==ALARMED_PIXELS?"Alarmed Pixels":( + check_method==FILTERED_PIXELS?"FilteredPixels":( + check_method==BLOBS?"Blobs":"Unknown" + ))); + sprintf( output+strlen(output), " Min Pixel Threshold : %d\n", min_pixel_threshold ); + sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_pixel_threshold ); + sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels ); + sprintf( output+strlen(output), " Max Alarm Pixels : %d\n", max_alarm_pixels ); + sprintf( output+strlen(output), " Filter Box : %d,%d\n", filter_box.X(), filter_box.Y() ); + sprintf( output+strlen(output), " Min Filter Pixels : %d\n", min_filter_pixels ); + sprintf( output+strlen(output), " Max Filter Pixels : %d\n", max_filter_pixels ); + sprintf( output+strlen(output), " Min Blob Pixels : %d\n", min_blob_pixels ); + sprintf( output+strlen(output), " Max Blob Pixels : %d\n", max_blob_pixels ); + sprintf( output+strlen(output), " Min Blobs : %d\n", min_blobs ); + sprintf( output+strlen(output), " Max Blobs : %d\n", max_blobs ); + return( true ); +} + +void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum) { + uint32_t pixelsalarmed = 0; + uint32_t pixelsdifference = 0; + uint8_t *pdiff; + const uint8_t *ppoly; + uint8_t calc_max_pixel_threshold = 255; + unsigned int lo_y; + unsigned int hi_y; + unsigned int lo_x; + unsigned int hi_x; + + if(max_pixel_threshold) + calc_max_pixel_threshold = max_pixel_threshold; + + lo_y = polygon.LoY(); + hi_y = polygon.HiY(); + for ( unsigned int y = lo_y; y <= hi_y; y++ ) + { + lo_x = ranges[y].lo_x; + hi_x = ranges[y].hi_x; + + Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x ); + pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); + ppoly = ppoly_image->Buffer( lo_x, y ); + + for ( unsigned int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) + { + if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) + { + pixelsalarmed++; + pixelsdifference += *pdiff; + *pdiff = WHITE; + } + else + { + *pdiff = BLACK; + } + } + } + + /* Store the results */ + *pixel_count = pixelsalarmed; + *pixel_sum = pixelsdifference; + Debug( 7, "STORED"); +} diff --git a/src/zm_zone.cpp.orig b/src/zm_zone.cpp.orig new file mode 100644 index 000000000..0acf7a045 --- /dev/null +++ b/src/zm_zone.cpp.orig @@ -0,0 +1,1035 @@ +// +// ZoneMinder Zone Class Implementation, $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. +// + +#include "zm.h" +#include "zm_db.h" +#include "zm_zone.h" +#include "zm_image.h" +#include "zm_monitor.h" + +void Zone::Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames ) +{ + monitor = p_monitor; + + id = p_id; + label = new char[strlen(p_label)+1]; + strcpy( label, p_label ); + type = p_type; + polygon = p_polygon; + alarm_rgb = p_alarm_rgb; + check_method = p_check_method; + min_pixel_threshold = p_min_pixel_threshold; + max_pixel_threshold = p_max_pixel_threshold; + min_alarm_pixels = p_min_alarm_pixels; + max_alarm_pixels = p_max_alarm_pixels; + filter_box = p_filter_box; + min_filter_pixels = p_min_filter_pixels; + max_filter_pixels = p_max_filter_pixels; + min_blob_pixels = p_min_blob_pixels; + max_blob_pixels = p_max_blob_pixels; + min_blobs = p_min_blobs; + max_blobs = p_max_blobs; + overload_frames = p_overload_frames; + + Debug( 1, "Initialised zone %d/%s - %d - %dx%d - Rgb:%06x, CM:%d, MnAT:%d, MxAT:%d, MnAP:%d, MxAP:%d, FB:%dx%d, MnFP:%d, MxFP:%d, MnBS:%d, MxBS:%d, MnB:%d, MxB:%d, OF: %d", id, label, type, polygon.Width(), polygon.Height(), alarm_rgb, check_method, min_pixel_threshold, max_pixel_threshold, min_alarm_pixels, max_alarm_pixels, filter_box.X(), filter_box.Y(), min_filter_pixels, max_filter_pixels, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs, overload_frames ); + + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + image = 0; + score = 0; + + overload_count = 0; + + pg_image = new Image( monitor->Width(), monitor->Height(), 1, ZM_SUBPIX_ORDER_NONE); + pg_image->Clear(); + pg_image->Fill( 0xff, polygon ); + pg_image->Outline( 0xff, polygon ); + + ranges = new Range[monitor->Height()]; + for ( int y = 0; y < monitor->Height(); y++) + { + ranges[y].lo_x = -1; + ranges[y].hi_x = -1; + ranges[y].off_x = 0; + const uint8_t *ppoly = pg_image->Buffer( 0, y ); + for ( int x = 0; x < monitor->Width(); x++, ppoly++ ) + { + if ( *ppoly ) + { + if ( ranges[y].lo_x == -1 ) + { + ranges[y].lo_x = x; + } + if ( ranges[y].hi_x < x ) + { + ranges[y].hi_x = x; + } + } + } + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-poly.jpg", config.dir_events, monitor->Name(), id); + } + pg_image->WriteJpeg( diag_path ); + } +} + +Zone::~Zone() +{ + delete[] label; + delete image; + delete pg_image; + delete[] ranges; +} + +void Zone::RecordStats( const Event *event ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "insert into Stats set MonitorId=%d, ZoneId=%d, EventId=%d, FrameId=%d, PixelDiff=%d, AlarmPixels=%d, FilterPixels=%d, BlobPixels=%d, Blobs=%d, MinBlobSize=%d, MaxBlobSize=%d, MinX=%d, MinY=%d, MaxX=%d, MaxY=%d, Score=%d", monitor->Id(), id, event->Id(), event->Frames()+1, pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, min_blob_size, max_blob_size, alarm_box.LoX(), alarm_box.LoY(), alarm_box.HiX(), alarm_box.HiY(), score ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't insert event stats: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } +} + +bool Zone::CheckAlarms( const Image *delta_image ) +{ + bool alarm = false; + + ResetStats(); + + if ( overload_count ) + { + Info( "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + Debug( 4, "In overload mode, %d frames of %d remaining", overload_count, overload_frames ); + overload_count--; + return( false ); + } + + delete image; + // Get the difference image + Image *diff_image = image = new Image( *delta_image ); + int diff_width = diff_image->Width(); + uint8_t* diff_buff = (uint8_t*)diff_image->Buffer(); + uint8_t* pdiff; + const uint8_t* ppoly; + + unsigned int pixel_diff_count = 0; + + int alarm_lo_x = 0; + int alarm_hi_x = 0; + int alarm_lo_y = 0; + int alarm_hi_y = 0; + + int alarm_mid_x = -1; + int alarm_mid_y = -1; + + unsigned int lo_y = polygon.LoY(); + unsigned int lo_x = polygon.LoX(); + unsigned int hi_x = polygon.HiX(); + unsigned int hi_y = polygon.HiY(); + + Debug( 4, "Checking alarms for zone %d/%s in lines %d -> %d", id, label, lo_y, hi_y ); + + + Debug( 5, "Checking for alarmed pixels" ); + /* if(config.cpu_extensions && sseversion >= 20) { + sse2_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } else { + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + } */ + std_alarmedpixels(diff_image, pg_image, &alarm_pixels, &pixel_diff_count); + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%s/diag-%d-%d.jpg", config.dir_events, monitor->Name(), id, 1 ); + } + diff_image->WriteJpeg( diag_path ); + } + + if ( pixel_diff_count && alarm_pixels ) + pixel_diff = pixel_diff_count/alarm_pixels; + Debug( 5, "Got %d alarmed pixels, need %d -> %d, avg pixel diff %d", alarm_pixels, min_alarm_pixels, max_alarm_pixels, pixel_diff ); + + if( alarm_pixels ) { + if( min_alarm_pixels && (alarm_pixels < min_alarm_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_alarm_pixels && (alarm_pixels > max_alarm_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No alarmed pixels */ + return (false); + } + + score = (100*alarm_pixels)/polygon.Area(); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + if ( check_method >= FILTERED_PIXELS ) + { + int bx = filter_box.X(); + int by = filter_box.Y(); + int bx1 = bx-1; + int by1 = by-1; + + Debug( 5, "Checking for filtered pixels" ); + if ( bx > 1 || by > 1 ) + { + // Now remove any pixels smaller than our filter size + unsigned char *cpdiff; + int ldx, hdx, ldy, hdy; + bool block; + for ( int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; + + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + // Check participation in an X block + ldx = (x>=(lo_x+bx1))?-bx1:lo_x-x; + hdx = (x<=(hi_x-bx1))?0:((hi_x-x)-bx1); + ldy = (y>=(lo_y+by1))?-by1:lo_y-y; + hdy = (y<=(hi_y-by1))?0:((hi_y-y)-by1); + block = false; + for ( int dy = ldy; !block && dy <= hdy; dy++ ) + { + for ( int dx = ldx; !block && dx <= hdx; dx++ ) + { + block = true; + for ( int dy2 = 0; block && dy2 < by; dy2++ ) + { + for ( int dx2 = 0; block && dx2 < bx; dx2++ ) + { + cpdiff = diff_buff + (((y+dy+dy2)*diff_width) + (x+dx+dx2)); + if ( !*cpdiff ) + { + block = false; + } + } + } + } + } + if ( !block ) + { + *pdiff = BLACK; + continue; + } + alarm_filter_pixels++; + } + } + } + } + else + { + alarm_filter_pixels = alarm_pixels; + } + + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 2 ); + } + diff_image->WriteJpeg( diag_path ); + } + + Debug( 5, "Got %d filtered pixels, need %d -> %d", alarm_filter_pixels, min_filter_pixels, max_filter_pixels ); + + if( alarm_filter_pixels ) { + if( min_filter_pixels && (alarm_filter_pixels < min_filter_pixels) ) { + /* Not enough pixels alarmed */ + return (false); + } else if( max_filter_pixels && (alarm_filter_pixels > max_filter_pixels) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No filtered pixels */ + return (false); + } + + score = (100*alarm_filter_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + if ( check_method >= BLOBS ) + { + Debug( 5, "Checking for blob pixels" ); + typedef struct { unsigned char tag; int count; int lo_x; int hi_x; int lo_y; int hi_y; } BlobStats; + BlobStats blob_stats[256]; + memset( blob_stats, 0, sizeof(BlobStats)*256 ); + uint8_t *spdiff; + uint8_t last_x, last_y; + BlobStats *bsx, *bsy; + BlobStats *bsm, *bss; + for ( int y = lo_y; y <= hi_y; y++ ) + { + int lo_x = ranges[y].lo_x; + int hi_x = ranges[y].hi_x; + + pdiff = (uint8_t*)diff_image->Buffer( lo_x, y ); + for ( int x = lo_x; x <= hi_x; x++, pdiff++ ) + { + if ( *pdiff == WHITE ) + { + Debug( 9, "Got white pixel at %d,%d (%p)", x, y, pdiff ); + //last_x = (x>lo_x)?*(pdiff-1):0; + //last_y = (y>lo_y&&x>=last_lo_x&&x<=last_hi_x)?*(pdiff-diff_width):0; + + last_x = 0; + if(x > 0) { + if((x-1) >= lo_x) { + last_x = *(pdiff-1); + } + } + + last_y = 0; + if(y > 0) { + if((y-1) >= lo_y && ranges[(y-1)].lo_x <= x && ranges[(y-1)].hi_x >= x) { + last_y = *(pdiff-diff_width); + } + } + + if ( last_x ) + { + Debug( 9, "Left neighbour is %d", last_x ); + bsx = &blob_stats[last_x]; + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + bsy = &blob_stats[last_y]; + if ( last_x == last_y ) + { + Debug( 9, "Matching neighbours, setting to %d", last_x ); + // Add to the blob from the x side (either side really) + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( y > bsx->hi_y ) bsx->hi_y = y; + } + else + { + // Aggregate blobs + bsm = bsx->count>=bsy->count?bsx:bsy; + bss = bsm==bsx?bsy:bsx; + + Debug( 9, "Different neighbours, setting pixels of %d to %d", bss->tag, bsm->tag ); + Debug( 9, "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Debug( 9, "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + // Now change all those pixels to the other setting + int changed = 0; + for ( int sy = bss->lo_y; sy <= bss->hi_y; sy++) + { + int lo_sx = bss->lo_x>=ranges[sy].lo_x?bss->lo_x:ranges[sy].lo_x; + int hi_sx = bss->hi_x<=ranges[sy].hi_x?bss->hi_x:ranges[sy].hi_x; + + Debug( 9, "Changing %d, %d->%d", sy, lo_sx, hi_sx ); + Debug( 9, "Range %d, %d->%d", sy, ranges[sy].lo_x, ranges[sy].hi_x ); + spdiff = diff_buff + ((diff_width * sy) + lo_sx); + for ( int sx = lo_sx; sx <= hi_sx; sx++, spdiff++ ) + { + Debug( 9, "Pixel at %d,%d (%p) is %d", sx, sy, spdiff, *spdiff ); + if ( *spdiff == bss->tag ) + { + Debug( 9, "Setting pixel" ); + *spdiff = bsm->tag; + changed++; + } + } + } + *pdiff = bsm->tag; + alarm_blob_pixels++; + if ( !changed ) + { + Info( "Master blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bsm->tag, bsm->count, bsm->lo_x, bsm->hi_x, bsm->lo_y, bsm->hi_y ); + Info( "Slave blob t:%d, c:%d, lx:%d, hx:%d, ly:%d, hy:%d", bss->tag, bss->count, bss->lo_x, bss->hi_x, bss->lo_y, bss->hi_y ); + Error( "No pixels changed, exiting" ); + exit( -1 ); + } + + // Merge the slave blob into the master + bsm->count += bss->count+1; + if ( x > bsm->hi_x ) bsm->hi_x = x; + if ( y > bsm->hi_y ) bsm->hi_y = y; + if ( bss->lo_x < bsm->lo_x ) bsm->lo_x = bss->lo_x; + if ( bss->lo_y < bsm->lo_y ) bsm->lo_y = bss->lo_y; + if ( bss->hi_x > bsm->hi_x ) bsm->hi_x = bss->hi_x; + if ( bss->hi_y > bsm->hi_y ) bsm->hi_y = bss->hi_y; + + alarm_blobs--; + + Debug( 6, "Merging blob %d with %d at %d,%d, %d current blobs", bss->tag, bsm->tag, x, y, alarm_blobs ); + + // Clear out the old blob + bss->tag = 0; + bss->count = 0; + bss->lo_x = 0; + bss->lo_y = 0; + bss->hi_x = 0; + bss->hi_y = 0; + } + } + else + { + Debug( 9, "Setting to left neighbour %d", last_x ); + // Add to the blob from the x side + *pdiff = last_x; + alarm_blob_pixels++; + bsx->count++; + if ( x > bsx->hi_x ) bsx->hi_x = x; + if ( y > bsx->hi_y ) bsx->hi_y = y; + } + } + else + { + if ( last_y ) + { + Debug( 9, "Top neighbour is %d", last_y ); + Debug( 9, "Setting to top neighbour %d", last_y ); + + // Add to the blob from the y side + BlobStats *bsy = &blob_stats[last_y]; + + *pdiff = last_y; + alarm_blob_pixels++; + bsy->count++; + if ( x > bsy->hi_x ) bsy->hi_x = x; + if ( y > bsy->hi_y ) bsy->hi_y = y; + } + else + { + // Create a new blob + int i; + for ( i = (WHITE-1); i > 0; i-- ) + { + BlobStats *bs = &blob_stats[i]; + // See if we can recycle one first, only if it's at least two rows up + if ( bs->count && bs->hi_y < (y-1) ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + } + if ( !bs->count ) + { + Debug( 9, "Creating new blob %d", i ); + *pdiff = i; + alarm_blob_pixels++; + bs->tag = i; + bs->count++; + bs->lo_x = bs->hi_x = x; + bs->lo_y = bs->hi_y = y; + alarm_blobs++; + + Debug( 6, "Created blob %d at %d,%d, %d current blobs", bs->tag, x, y, alarm_blobs ); + break; + } + } + if ( i == 0 ) + { + Warning( "Max blob count reached. Unable to allocate new blobs so terminating. Zone settings may be too sensitive." ); + x = hi_x+1; + y = hi_y+1; + } + } + } + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 3 ); + } + diff_image->WriteJpeg( diag_path ); + } + + if ( !alarm_blobs ) + { + return( false ); + } + + Debug( 5, "Got %d raw blob pixels, %d raw blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + + // Now eliminate blobs under the threshold + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( (min_blob_pixels && bs->count < min_blob_pixels) || (max_blob_pixels && bs->count > max_blob_pixels) ) + { + if ( config.create_analysis_images || config.record_diag_images ) + { + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + *spdiff = BLACK; + } + } + } + } + alarm_blobs--; + alarm_blob_pixels -= bs->count; + + Debug( 6, "Eliminated blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + + bs->tag = 0; + bs->count = 0; + bs->lo_x = 0; + bs->lo_y = 0; + bs->hi_x = 0; + bs->hi_y = 0; + } + else + { + Debug( 6, "Preserved blob %d, %d pixels (%d,%d - %d,%d), %d current blobs", i, bs->count, bs->lo_x, bs->lo_y, bs->hi_x, bs->hi_y, alarm_blobs ); + if ( !min_blob_size || bs->count < min_blob_size ) min_blob_size = bs->count; + if ( !max_blob_size || bs->count > max_blob_size ) max_blob_size = bs->count; + } + } + } + if ( config.record_diag_images ) + { + static char diag_path[PATH_MAX] = ""; + if ( !diag_path[0] ) + { + snprintf( diag_path, sizeof(diag_path), "%s/%d/diag-%d-%d.jpg", config.dir_events, monitor->Id(), id, 4 ); + } + diff_image->WriteJpeg( diag_path ); + } + Debug( 5, "Got %d blob pixels, %d blobs, need %d -> %d, %d -> %d", alarm_blob_pixels, alarm_blobs, min_blob_pixels, max_blob_pixels, min_blobs, max_blobs ); + + if( alarm_blobs ) { + if( min_blobs && (alarm_blobs < min_blobs) ) { + /* Not enough pixels alarmed */ + return (false); + } else if(max_blobs && (alarm_blobs > max_blobs) ) { + /* Too many pixels alarmed */ + overload_count = overload_frames; + return (false); + } + } else { + /* No blobs */ + return (false); + } + + score = (100*alarm_blob_pixels)/(polygon.Area()); + if(score < 1) + score = 1; /* Fix for score of 0 when frame meets thresholds but alarmed area is not big enough */ + Debug( 5, "Current score is %d", score ); + + alarm_lo_x = polygon.HiX()+1; + alarm_hi_x = polygon.LoX()-1; + alarm_lo_y = polygon.HiY()+1; + alarm_hi_y = polygon.LoY()-1; + for ( int i = 1; i < WHITE; i++ ) + { + BlobStats *bs = &blob_stats[i]; + if ( bs->count ) + { + if ( bs->count == max_blob_size ) + { + if ( config.weighted_alarm_centres ) + { + unsigned long x_total = 0; + unsigned long y_total = 0; + + for ( int sy = bs->lo_y; sy <= bs->hi_y; sy++ ) + { + spdiff = diff_buff + ((diff_width * sy) + bs->lo_x); + for ( int sx = bs->lo_x; sx <= bs->hi_x; sx++, spdiff++ ) + { + if ( *spdiff == bs->tag ) + { + x_total += sx; + y_total += sy; + } + } + } + alarm_mid_x = int(round(x_total/bs->count)); + alarm_mid_y = int(round(y_total/bs->count)); + } + else + { + alarm_mid_x = int((bs->hi_x+bs->lo_x+1)/2); + alarm_mid_y = int((bs->hi_y+bs->lo_y+1)/2); + } + } + + if ( alarm_lo_x > bs->lo_x ) alarm_lo_x = bs->lo_x; + if ( alarm_lo_y > bs->lo_y ) alarm_lo_y = bs->lo_y; + if ( alarm_hi_x < bs->hi_x ) alarm_hi_x = bs->hi_x; + if ( alarm_hi_y < bs->hi_y ) alarm_hi_y = bs->hi_y; + } + } + } + else + { + alarm_mid_x = int((alarm_hi_x+alarm_lo_x+1)/2); + alarm_mid_y = int((alarm_hi_y+alarm_lo_y+1)/2); + } + } + + if ( type == INCLUSIVE ) + { + // score >>= 1; + score /= 2; + } + else if ( type == EXCLUSIVE ) + { + // score <<= 1; + score *= 2; + + } + + Debug( 5, "Adjusted score is %d", score ); + + // Now outline the changed region + if ( score ) + { + alarm = true; + + alarm_box = Box( Coord( alarm_lo_x, alarm_lo_y ), Coord( alarm_hi_x, alarm_hi_y ) ); + + //if ( monitor->followMotion() ) + if ( true ) + { + alarm_centre = Coord( alarm_mid_x, alarm_mid_y ); + } + else + { + alarm_centre = alarm_box.Centre(); + } + + if ( (type < PRECLUSIVE) && check_method >= BLOBS && config.create_analysis_images ) + { + + // First mask out anything we don't want + for ( int y = lo_y; y <= hi_y; y++ ) + { + pdiff = diff_buff + ((diff_width * y) + lo_x); + + int lo_x2 = ranges[y].lo_x; + int hi_x2 = ranges[y].hi_x; + + int lo_gap = lo_x2-lo_x; + if ( lo_gap > 0 ) + { + if ( lo_gap == 1 ) + { + *pdiff++ = BLACK; + } + else + { + memset( pdiff, BLACK, lo_gap ); + pdiff += lo_gap; + } + } + + ppoly = pg_image->Buffer( lo_x2, y ); + for ( int x = lo_x2; x <= hi_x2; x++, pdiff++, ppoly++ ) + { + if ( !*ppoly ) + { + *pdiff = BLACK; + } + } + + int hi_gap = hi_x-hi_x2; + if ( hi_gap > 0 ) + { + if ( hi_gap == 1 ) + { + *pdiff = BLACK; + } + else + { + memset( pdiff, BLACK, hi_gap ); + } + } + } + + if( monitor->Colours() == ZM_COLOUR_GRAY8 ) { + image = diff_image->HighlightEdges( alarm_rgb, ZM_COLOUR_RGB24, ZM_SUBPIX_ORDER_RGB, &polygon.Extent() ); + } else { + image = diff_image->HighlightEdges( alarm_rgb, monitor->Colours(), monitor->SubpixelOrder(), &polygon.Extent() ); + } + + // Only need to delete this when 'image' becomes detached and points somewhere else + delete diff_image; + } + else + { + delete image; + image = 0; + } + + Debug( 1, "%s: Pixel Diff: %d, Alarm Pixels: %d, Filter Pixels: %d, Blob Pixels: %d, Blobs: %d, Score: %d", Label(), pixel_diff, alarm_pixels, alarm_filter_pixels, alarm_blob_pixels, alarm_blobs, score ); + } + return( true ); +} + +bool Zone::ParsePolygonString( const char *poly_string, Polygon &polygon ) +{ + Debug( 3, "Parsing polygon string '%s'", poly_string ); + + char *str_ptr = new char[strlen(poly_string)+1]; + char *str = str_ptr; + strcpy( str, poly_string ); + + char *ws; + int n_coords = 0; + int max_n_coords = strlen(str)/4; + Coord *coords = new Coord[max_n_coords]; + while( true ) + { + if ( *str == '\0' ) + { + break; + } + ws = strchr( str, ' ' ); + if ( ws ) + { + *ws = '\0'; + } + char *cp = strchr( str, ',' ); + if ( !cp ) + { + Error( "Bogus coordinate %s found in polygon string", str ); + delete[] coords; + delete[] str_ptr; + return( false ); + } + else + { + *cp = '\0'; + char *xp = str; + char *yp = cp+1; + + int x = atoi(xp); + int y = atoi(yp); + + Debug( 3, "Got coordinate %d,%d from polygon string", x, y ); +#if 0 + if ( x < 0 ) + x = 0; + else if ( x >= width ) + x = width-1; + if ( y < 0 ) + y = 0; + else if ( y >= height ) + y = height-1; +#endif + coords[n_coords++] = Coord( x, y ); + } + if ( ws ) + str = ws+1; + else + break; + } + polygon = Polygon( n_coords, coords ); + + Debug( 3, "Successfully parsed polygon string" ); + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + + delete[] coords; + delete[] str_ptr; + + return( true ); +} + +bool Zone::ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ) +{ + Debug( 3, "Parsing zone string '%s'", zone_string ); + + char *str_ptr = new char[strlen(zone_string)+1]; + char *str = str_ptr; + strcpy( str, zone_string ); + + char *ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No initial whitespace found in zone string '%s', finishing", str ); + } + zone_id = strtol( str, 0, 10 ); + Debug( 3, "Got zone %d from zone string", zone_id ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } + + *ws = '\0'; + str = ws+1; + + ws = strchr( str, ' ' ); + if ( !ws ) + { + Debug( 3, "No secondary whitespace found in zone string '%s', finishing", zone_string ); + } + colour = strtol( str, 0, 16 ); + Debug( 3, "Got colour %06x from zone string", colour ); + if ( !ws ) + { + delete str_ptr; + return( true ); + } + *ws = '\0'; + str = ws+1; + + bool result = ParsePolygonString( str, polygon ); + + //printf( "Area: %d\n", pg.Area() ); + //printf( "Centre: %d,%d\n", pg.Centre().X(), pg.Centre().Y() ); + + delete[] str_ptr; + + return( result ); +} + +int Zone::Load( Monitor *monitor, Zone **&zones ) +{ + static char sql[ZM_SQL_MED_BUFSIZ]; + snprintf( sql, sizeof(sql), "select Id,Name,Type+0,Units,NumCoords,Coords,AlarmRGB,CheckMethod+0,MinPixelThreshold,MaxPixelThreshold,MinAlarmPixels,MaxAlarmPixels,FilterX,FilterY,MinFilterPixels,MaxFilterPixels,MinBlobPixels,MaxBlobPixels,MinBlobs,MaxBlobs,OverloadFrames from Zones where MonitorId = %d order by Type, Id", monitor->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 ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_zones = mysql_num_rows( result ); + Debug( 1, "Got %d zones for monitor %s", n_zones, monitor->Name() ); + delete[] zones; + zones = new Zone *[n_zones]; + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int col = 0; + + int Id = atoi(dbrow[col++]); + const char *Name = dbrow[col++]; + int Type = atoi(dbrow[col++]); + const char *Units = dbrow[col++]; + /* int NumCoords = */ atoi(dbrow[col++]); + const char *Coords = dbrow[col++]; + int AlarmRGB = dbrow[col]?atoi(dbrow[col]):0; col++; + int CheckMethod = atoi(dbrow[col++]); + int MinPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxPixelThreshold = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxAlarmPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterX = dbrow[col]?atoi(dbrow[col]):0; col++; + int FilterY = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxFilterPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobPixels = dbrow[col]?atoi(dbrow[col]):0; col++; + int MinBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int MaxBlobs = dbrow[col]?atoi(dbrow[col]):0; col++; + int OverloadFrames = dbrow[col]?atoi(dbrow[col]):0; col++; + + /* HTML colour code is actually BGR in memory, we want RGB */ + AlarmRGB = rgb_convert(AlarmRGB, ZM_SUBPIX_ORDER_BGR); + + Debug( 5, "Parsing polygon %s", Coords ); + Polygon polygon; + if ( !ParsePolygonString( Coords, polygon ) ) + Panic( "Unable to parse polygon string '%s' for zone %d/%s for monitor %s", Coords, Id, Name, monitor->Name() ); + + if ( polygon.LoX() < 0 || polygon.HiX() >= monitor->Width() || polygon.LoY() < 0 || polygon.HiY() >= monitor->Height() ) + Panic( "Zone %d/%s for monitor %s extends outside of image dimensions, %d, %d, %d, %d", Id, Name, monitor->Name(), polygon.LoX(), polygon.LoY(), polygon.HiX(), polygon.HiY() ); + + if ( false && !strcmp( Units, "Percent" ) ) + { + MinAlarmPixels = (MinAlarmPixels*polygon.Area())/100; + MaxAlarmPixels = (MaxAlarmPixels*polygon.Area())/100; + MinFilterPixels = (MinFilterPixels*polygon.Area())/100; + MaxFilterPixels = (MaxFilterPixels*polygon.Area())/100; + MinBlobPixels = (MinBlobPixels*polygon.Area())/100; + MaxBlobPixels = (MaxBlobPixels*polygon.Area())/100; + } + + if ( atoi(dbrow[2]) == Zone::INACTIVE ) + { + zones[i] = new Zone( monitor, Id, Name, polygon ); + } + else + { + zones[i] = new Zone( monitor, Id, Name, (Zone::ZoneType)Type, polygon, AlarmRGB, (Zone::CheckMethod)CheckMethod, MinPixelThreshold, MaxPixelThreshold, MinAlarmPixels, MaxAlarmPixels, Coord( FilterX, FilterY ), MinFilterPixels, MaxFilterPixels, MinBlobPixels, MaxBlobPixels, MinBlobs, MaxBlobs, OverloadFrames ); + } + } + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + return( n_zones ); +} + +bool Zone::DumpSettings( char *output, bool /*verbose*/ ) +{ + output[0] = 0; + + sprintf( output+strlen(output), " Id : %d\n", id ); + sprintf( output+strlen(output), " Label : %s\n", label ); + sprintf( output+strlen(output), " Type: %d - %s\n", type, + type==ACTIVE?"Active":( + type==INCLUSIVE?"Inclusive":( + type==EXCLUSIVE?"Exclusive":( + type==PRECLUSIVE?"Preclusive":( + type==INACTIVE?"Inactive":"Unknown" + ))))); + sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() ); + for ( int i = 0; i < polygon.getNumCoords(); i++ ) + { + sprintf( output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).X(), polygon.getCoord( i ).Y() ); + } + sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb ); + sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method, + check_method==ALARMED_PIXELS?"Alarmed Pixels":( + check_method==FILTERED_PIXELS?"FilteredPixels":( + check_method==BLOBS?"Blobs":"Unknown" + ))); + sprintf( output+strlen(output), " Min Pixel Threshold : %d\n", min_pixel_threshold ); + sprintf( output+strlen(output), " Max Pixel Threshold : %d\n", max_pixel_threshold ); + sprintf( output+strlen(output), " Min Alarm Pixels : %d\n", min_alarm_pixels ); + sprintf( output+strlen(output), " Max Alarm Pixels : %d\n", max_alarm_pixels ); + sprintf( output+strlen(output), " Filter Box : %d,%d\n", filter_box.X(), filter_box.Y() ); + sprintf( output+strlen(output), " Min Filter Pixels : %d\n", min_filter_pixels ); + sprintf( output+strlen(output), " Max Filter Pixels : %d\n", max_filter_pixels ); + sprintf( output+strlen(output), " Min Blob Pixels : %d\n", min_blob_pixels ); + sprintf( output+strlen(output), " Max Blob Pixels : %d\n", max_blob_pixels ); + sprintf( output+strlen(output), " Min Blobs : %d\n", min_blobs ); + sprintf( output+strlen(output), " Max Blobs : %d\n", max_blobs ); + return( true ); +} + +void Zone::std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum) { + uint32_t pixelsalarmed = 0; + uint32_t pixelsdifference = 0; + uint8_t *pdiff; + const uint8_t *ppoly; + uint8_t calc_max_pixel_threshold = 255; + unsigned int lo_y; + unsigned int hi_y; + unsigned int lo_x; + unsigned int hi_x; + + if(max_pixel_threshold) + calc_max_pixel_threshold = max_pixel_threshold; + + lo_y = polygon.LoY(); + hi_y = polygon.HiY(); + for ( int y = lo_y; y <= hi_y; y++ ) + { + lo_x = ranges[y].lo_x; + hi_x = ranges[y].hi_x; + + Debug( 7, "Checking line %d from %d -> %d", y, lo_x, hi_x ); + pdiff = (uint8_t*)pdiff_image->Buffer( lo_x, y ); + ppoly = ppoly_image->Buffer( lo_x, y ); + + for ( int x = lo_x; x <= hi_x; x++, pdiff++, ppoly++ ) + { + if ( *ppoly && (*pdiff > min_pixel_threshold) && (*pdiff <= calc_max_pixel_threshold) ) + { + pixelsalarmed++; + pixelsdifference += *pdiff; + *pdiff = WHITE; + } + else + { + *pdiff = BLACK; + } + } + } + + /* Store the results */ + *pixel_count = pixelsalarmed; + *pixel_sum = pixelsdifference; +} diff --git a/src/zm_zone.h b/src/zm_zone.h new file mode 100644 index 000000000..3eb8d7815 --- /dev/null +++ b/src/zm_zone.h @@ -0,0 +1,164 @@ +// +// ZoneMinder Zone Class Interfaces, $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. +// + +#ifndef ZM_ZONE_H +#define ZM_ZONE_H + +#include "zm_rgb.h" +#include "zm_coord.h" +#include "zm_poly.h" +#include "zm_image.h" +#include "zm_event.h" + +class Monitor; + +// +// This describes a 'zone', or an area of an image that has certain +// detection characteristics. +// +class Zone +{ +protected: + struct Range + { + int lo_x; + int hi_x; + int off_x; + }; + +public: + typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType; + typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod; + +protected: + // Inputs + Monitor *monitor; + + int id; + char *label; + ZoneType type; + Polygon polygon; + Rgb alarm_rgb; + CheckMethod check_method; + + int min_pixel_threshold; + int max_pixel_threshold; + + int min_alarm_pixels; + int max_alarm_pixels; + + Coord filter_box; + int min_filter_pixels; + int max_filter_pixels; + + int min_blob_pixels; + int max_blob_pixels; + int min_blobs; + int max_blobs; + + int overload_frames; + + // Outputs/Statistics + bool alarmed; + int pixel_diff; + unsigned int alarm_pixels; + int alarm_filter_pixels; + int alarm_blob_pixels; + int alarm_blobs; + int min_blob_size; + int max_blob_size; + Box alarm_box; + Coord alarm_centre; + unsigned int score; + Image *pg_image; + Range *ranges; + Image *image; + + int overload_count; + +protected: + void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames ); + void std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum); + +public: + Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0 ) + { + Setup( p_monitor, p_id, p_label, p_type, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0 ) + { + Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon ) + { + Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0 ); + } + +public: + ~Zone(); + + inline int Id() const { return( id ); } + inline const char *Label() const { return( label ); } + inline ZoneType Type() const { return( type ); } + inline bool IsActive() const { return( type == ACTIVE ); } + inline bool IsInclusive() const { return( type == INCLUSIVE ); } + inline bool IsExclusive() const { return( type == EXCLUSIVE ); } + inline bool IsPreclusive() const { return( type == PRECLUSIVE ); } + inline bool IsInactive() const { return( type == INACTIVE ); } + inline const Image *AlarmImage() const { return( image ); } + inline const Polygon &GetPolygon() const { return( polygon ); } + inline bool Alarmed() const { return( alarmed ); } + inline void SetAlarm() { alarmed = true; } + inline void ClearAlarm() { alarmed = false; } + inline Coord GetAlarmCentre() const { return( alarm_centre ); } + inline unsigned int Score() const { return( score ); } + + inline void ResetStats() + { + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + score = 0; + } + void RecordStats( const Event *event ); + bool CheckAlarms( const Image *delta_image ); + bool DumpSettings( char *output, bool verbose ); + + static bool ParsePolygonString( const char *polygon_string, Polygon &polygon ); + static bool ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ); + static int Load( Monitor *monitor, Zone **&zones ); + //================================================= + bool CheckOverloadCount(); + int GetOverloadCount(); + void SetOverloadCount(int nOverCount); + int GetOverloadFrames(); + void SetScore(unsigned int nScore); + void SetAlarmImage(const Image* srcImage); + + inline const Image *getPgImage() const { return( pg_image ); } + inline const Range *getRanges() const { return( ranges ); } + +}; + +#endif // ZM_ZONE_H diff --git a/src/zm_zone.h.orig b/src/zm_zone.h.orig new file mode 100644 index 000000000..6aa45e13d --- /dev/null +++ b/src/zm_zone.h.orig @@ -0,0 +1,153 @@ +// +// ZoneMinder Zone Class Interfaces, $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. +// + +#ifndef ZM_ZONE_H +#define ZM_ZONE_H + +#include "zm_rgb.h" +#include "zm_coord.h" +#include "zm_poly.h" +#include "zm_image.h" +#include "zm_event.h" + +class Monitor; + +// +// This describes a 'zone', or an area of an image that has certain +// detection characteristics. +// +class Zone +{ +protected: + struct Range + { + int lo_x; + int hi_x; + int off_x; + }; + +public: + typedef enum { ACTIVE=1, INCLUSIVE, EXCLUSIVE, PRECLUSIVE, INACTIVE } ZoneType; + typedef enum { ALARMED_PIXELS=1, FILTERED_PIXELS, BLOBS } CheckMethod; + +protected: + // Inputs + Monitor *monitor; + + int id; + char *label; + ZoneType type; + Polygon polygon; + Rgb alarm_rgb; + CheckMethod check_method; + + int min_pixel_threshold; + int max_pixel_threshold; + + int min_alarm_pixels; + int max_alarm_pixels; + + Coord filter_box; + int min_filter_pixels; + int max_filter_pixels; + + int min_blob_pixels; + int max_blob_pixels; + int min_blobs; + int max_blobs; + + int overload_frames; + + // Outputs/Statistics + bool alarmed; + int pixel_diff; + unsigned int alarm_pixels; + int alarm_filter_pixels; + int alarm_blob_pixels; + int alarm_blobs; + int min_blob_size; + int max_blob_size; + Box alarm_box; + Coord alarm_centre; + unsigned int score; + Image *pg_image; + Range *ranges; + Image *image; + + int overload_count; + +protected: + void Setup( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold, int p_max_pixel_threshold, int p_min_alarm_pixels, int p_max_alarm_pixels, const Coord &p_filter_box, int p_min_filter_pixels, int p_max_filter_pixels, int p_min_blob_pixels, int p_max_blob_pixels, int p_min_blobs, int p_max_blobs, int p_overload_frames ); + void std_alarmedpixels(Image* pdiff_image, const Image* ppoly_image, unsigned int* pixel_count, unsigned int* pixel_sum); + +public: + Zone( Monitor *p_monitor, int p_id, const char *p_label, ZoneType p_type, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0 ) + { + Setup( p_monitor, p_id, p_label, p_type, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon, const Rgb p_alarm_rgb, CheckMethod p_check_method, int p_min_pixel_threshold=15, int p_max_pixel_threshold=0, int p_min_alarm_pixels=50, int p_max_alarm_pixels=75000, const Coord &p_filter_box=Coord( 3, 3 ), int p_min_filter_pixels=50, int p_max_filter_pixels=50000, int p_min_blob_pixels=10, int p_max_blob_pixels=0, int p_min_blobs=0, int p_max_blobs=0, int p_overload_frames=0 ) + { + Setup( p_monitor, p_id, p_label, Zone::ACTIVE, p_polygon, p_alarm_rgb, p_check_method, p_min_pixel_threshold, p_max_pixel_threshold, p_min_alarm_pixels, p_max_alarm_pixels, p_filter_box, p_min_filter_pixels, p_max_filter_pixels, p_min_blob_pixels, p_max_blob_pixels, p_min_blobs, p_max_blobs, p_overload_frames ); + } + Zone( Monitor *p_monitor, int p_id, const char *p_label, const Polygon &p_polygon ) + { + Setup( p_monitor, p_id, p_label, Zone::INACTIVE, p_polygon, RGB_BLACK, (Zone::CheckMethod)0, 0, 0, 0, 0, Coord( 0, 0 ), 0, 0, 0, 0, 0, 0, 0 ); + } + +public: + ~Zone(); + + inline int Id() const { return( id ); } + inline const char *Label() const { return( label ); } + inline ZoneType Type() const { return( type ); } + inline bool IsActive() const { return( type == ACTIVE ); } + inline bool IsInclusive() const { return( type == INCLUSIVE ); } + inline bool IsExclusive() const { return( type == EXCLUSIVE ); } + inline bool IsPreclusive() const { return( type == PRECLUSIVE ); } + inline bool IsInactive() const { return( type == INACTIVE ); } + inline const Image *AlarmImage() const { return( image ); } + inline const Polygon &GetPolygon() const { return( polygon ); } + inline bool Alarmed() const { return( alarmed ); } + inline void SetAlarm() { alarmed = true; } + inline void ClearAlarm() { alarmed = false; } + inline Coord GetAlarmCentre() const { return( alarm_centre ); } + inline unsigned int Score() const { return( score ); } + + inline void ResetStats() + { + alarmed = false; + pixel_diff = 0; + alarm_pixels = 0; + alarm_filter_pixels = 0; + alarm_blob_pixels = 0; + alarm_blobs = 0; + min_blob_size = 0; + max_blob_size = 0; + score = 0; + } + void RecordStats( const Event *event ); + bool CheckAlarms( const Image *delta_image ); + bool DumpSettings( char *output, bool verbose ); + + static bool ParsePolygonString( const char *polygon_string, Polygon &polygon ); + static bool ParseZoneString( const char *zone_string, int &zone_id, int &colour, Polygon &polygon ); + static int Load( Monitor *monitor, Zone **&zones ); +}; + +#endif // ZM_ZONE_H diff --git a/src/zma.cpp b/src/zma.cpp new file mode 100644 index 000000000..3de25bf12 --- /dev/null +++ b/src/zma.cpp @@ -0,0 +1,139 @@ +// +// ZoneMinder Analysis Daemon, $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. +// + +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_signal.h" +#include "zm_monitor.h" + +void Usage() +{ + fprintf( stderr, "zma -m \n" ); + fprintf( stderr, "Options:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + exit( 0 ); +} + +int main( int argc, char *argv[] ) +{ + srand( getpid() * time( 0 ) ); + + int id = -1; + + static struct option long_options[] = { + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + + while (1) + { + int option_index = 0; + + int c = getopt_long (argc, argv, "m:h", long_options, &option_index); + if (c == -1) + { + break; + } + + switch (c) + { + case 'm': + id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } + + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } + + if ( id < 0 ) + { + fprintf( stderr, "Bogus monitor %d\n", id ); + Usage(); + exit( 0 ); + } + + char log_id_string[16]; + snprintf( log_id_string, sizeof(log_id_string), "zma_m%d", id ); + + zmLoadConfig(); + + logInit( log_id_string ); + + ssedetect(); + + Monitor *monitor = Monitor::Load( id, true, Monitor::ANALYSIS ); + + if ( monitor ) + { + Info( "In mode %d/%d, warming up", monitor->GetFunction(), monitor->Enabled() ); + + if ( config.opt_frame_server ) + { + Event::OpenFrameSocket( monitor->Id() ); + } + + zmSetDefaultHupHandler(); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); + + sigset_t block_set; + sigemptyset( &block_set ); + + while( !zm_terminate ) + { + // Process the next image + sigprocmask( SIG_BLOCK, &block_set, 0 ); + if ( !monitor->Analyse() ) + { + usleep( monitor->Active()?ZM_SAMPLE_RATE:ZM_SUSPENDED_RATE ); + } + if ( zm_reload ) + { + monitor->Reload(); + zm_reload = false; + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } + delete monitor; + } + else + { + fprintf( stderr, "Can't find monitor with id of %d\n", id ); + } + return( 0 ); +} diff --git a/src/zmc.cpp b/src/zmc.cpp new file mode 100644 index 000000000..692c0b59e --- /dev/null +++ b/src/zmc.cpp @@ -0,0 +1,304 @@ +// +// ZoneMinder Capture Daemon, $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. +// + +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_time.h" +#include "zm_signal.h" +#include "zm_monitor.h" + +void Usage() +{ + fprintf( stderr, "zmc -d or -r -H -P -p or -f or -m \n" ); + + fprintf( stderr, "Options:\n" ); + fprintf( stderr, " -d, --device : For local cameras, device to access. E.g /dev/video0 etc\n" ); + fprintf( stderr, " -r -H -P -p : For remote cameras\n" ); + fprintf( stderr, " -f, --file : For local images, jpg file to access.\n" ); + fprintf( stderr, " -m, --monitor : For sources associated with a single monitor\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + exit( 0 ); +} + +int main( int argc, char *argv[] ) +{ + srand( getpid() * time( 0 ) ); + + const char *device = ""; + const char *protocol = ""; + const char *host = ""; + const char *port = ""; + const char *path = ""; + const char *file = ""; + int monitor_id = -1; + + static struct option long_options[] = { + {"device", 1, 0, 'd'}, + {"protocol", 1, 0, 'r'}, + {"host", 1, 0, 'H'}, + {"port", 1, 0, 'P'}, + {"path", 1, 0, 'p'}, + {"file", 1, 0, 'f'}, + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + + while (1) + { + int option_index = 0; + + int c = getopt_long (argc, argv, "d:H:P:p:f:m:h", long_options, &option_index); + if (c == -1) + { + break; + } + + switch (c) + { + case 'd': + device = optarg; + break; + case 'H': + host = optarg; + break; + case 'P': + port = optarg; + break; + case 'p': + path = optarg; + break; + case 'f': + file = optarg; + break; + case 'm': + monitor_id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } + + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } + + int modes = ( device[0]?1:0 + host[0]?1:0 + file[0]?1:0 + (monitor_id>0?1:0) ); + if ( modes > 1 ) + { + fprintf( stderr, "Only one of device, host/port/path, file or monitor id allowed\n" ); + Usage(); + exit( 0 ); + } + + if ( modes < 1 ) + { + fprintf( stderr, "One of device, host/port/path, file or monitor id must be specified\n" ); + Usage(); + exit( 0 ); + } + + char log_id_string[32] = ""; + if ( device[0] ) + { + const char *slash_ptr = strrchr( device, '/' ); + snprintf( log_id_string, sizeof(log_id_string), "zmc_d%s", slash_ptr?slash_ptr+1:device ); + } + else if ( host[0] ) + { + snprintf( log_id_string, sizeof(log_id_string), "zmc_h%s", host ); + } + else if ( file[0] ) + { + const char *slash_ptr = strrchr( file, '/' ); + snprintf( log_id_string, sizeof(log_id_string), "zmc_f%s", slash_ptr?slash_ptr+1:file ); + } + else + { + snprintf( log_id_string, sizeof(log_id_string), "zmc_m%d", monitor_id ); + } + + zmLoadConfig(); + + logInit( log_id_string ); + + ssedetect(); + + Monitor **monitors = 0; + int n_monitors = 0; +#if ZM_HAS_V4L + if ( device[0] ) + { + n_monitors = Monitor::LoadLocalMonitors( device, monitors, Monitor::CAPTURE ); + } + else +#endif // ZM_HAS_V4L + if ( host[0] ) + { + if ( !port ) + port = "80"; + n_monitors = Monitor::LoadRemoteMonitors( protocol, host, port, path, monitors, Monitor::CAPTURE ); + } + else if ( file[0] ) + { + n_monitors = Monitor::LoadFileMonitors( file, monitors, Monitor::CAPTURE ); + } + else + { + Monitor *monitor = Monitor::Load( monitor_id, true, Monitor::CAPTURE ); + if ( monitor ) + { + monitors = new Monitor *[1]; + monitors[0] = monitor; + n_monitors = 1; + } + } + + if ( !n_monitors ) + { + Error( "No monitors found" ); + exit ( -1 ); + } + + Info( "Starting Capture" ); + + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); + + sigset_t block_set; + sigemptyset( &block_set ); + + sigaddset( &block_set, SIGUSR1 ); + sigaddset( &block_set, SIGUSR2 ); + + if ( monitors[0]->PrimeCapture() < 0 ) + { + Error( "Failed to prime capture of initial monitor" ); + exit( -1 ); + } + + long *capture_delays = new long[n_monitors]; + long *alarm_capture_delays = new long[n_monitors]; + long *next_delays = new long[n_monitors]; + struct timeval * last_capture_times = new struct timeval[n_monitors]; + for ( int i = 0; i < n_monitors; i++ ) + { + last_capture_times[i].tv_sec = last_capture_times[i].tv_usec = 0; + capture_delays[i] = monitors[i]->GetCaptureDelay(); + alarm_capture_delays[i] = monitors[i]->GetAlarmCaptureDelay(); + } + + int result = 0; + struct timeval now; + struct DeltaTimeval delta_time; + while( !zm_terminate ) + { + sigprocmask( SIG_BLOCK, &block_set, 0 ); + for ( int i = 0; i < n_monitors; i++ ) + { + long min_delay = MAXINT; + + gettimeofday( &now, NULL ); + for ( int j = 0; j < n_monitors; j++ ) + { + if ( last_capture_times[j].tv_sec ) + { + DELTA_TIMEVAL( delta_time, now, last_capture_times[j], DT_PREC_3 ); + if ( monitors[i]->GetState() == Monitor::ALARM ) + next_delays[j] = alarm_capture_delays[j]-delta_time.delta; + else + next_delays[j] = capture_delays[j]-delta_time.delta; + if ( next_delays[j] < 0 ) + next_delays[j] = 0; + } + else + { + next_delays[j] = 0; + } + if ( next_delays[j] <= min_delay ) + { + min_delay = next_delays[j]; + } + } + + if ( next_delays[i] <= min_delay || next_delays[i] <= 0 ) + { + if ( monitors[i]->PreCapture() < 0 ) + { + Error( "Failed to pre-capture monitor %d (%d/%d)", monitors[i]->Id(), i, n_monitors ); + zm_terminate = true; + result = -1; + break; + } + if ( monitors[i]->Capture() < 0 ) + { + Error( "Failed to capture image from monitor %d (%d/%d)", monitors[i]->Id(), i, n_monitors ); + zm_terminate = true; + result = -1; + break; + } + if ( monitors[i]->PostCapture() < 0 ) + { + Error( "Failed to post-capture monitor %d (%d/%d)", monitors[i]->Id(), i, n_monitors ); + zm_terminate = true; + result = -1; + break; + } + + if ( next_delays[i] > 0 ) + { + gettimeofday( &now, NULL ); + DELTA_TIMEVAL( delta_time, now, last_capture_times[i], DT_PREC_3 ); + long sleep_time = next_delays[i]-delta_time.delta; + if ( sleep_time > 0 ) + { + usleep( sleep_time*(DT_MAXGRAN/DT_PREC_3) ); + } + } + gettimeofday( &(last_capture_times[i]), NULL ); + } + } + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } + for ( int i = 0; i < n_monitors; i++ ) + { + delete monitors[i]; + } + delete monitors; + delete [] alarm_capture_delays; + delete [] capture_delays; + delete [] next_delays; + delete [] last_capture_times; + + return( result ); +} diff --git a/src/zmf.cpp b/src/zmf.cpp new file mode 100644 index 000000000..bc7a54ee0 --- /dev/null +++ b/src/zmf.cpp @@ -0,0 +1,283 @@ +// +// ZoneMinder Image File Writer Implementation, $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. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_signal.h" +#include "zm_monitor.h" + +#include "zmf.h" + +int OpenSocket( int monitor_id ) +{ + int sd = socket( AF_UNIX, SOCK_STREAM, 0); + if ( sd < 0 ) + { + Error( "Can't create socket: %s", strerror(errno) ); + return( -1 ); + } + + char sock_path[PATH_MAX] = ""; + snprintf( sock_path, sizeof(sock_path), "%s/zmf-%d.sock", config.path_socks, monitor_id ); + if ( unlink( sock_path ) < 0 ) + { + Warning( "Can't unlink '%s': %s", sock_path, strerror(errno) ); + } + + struct sockaddr_un addr; + + strncpy( addr.sun_path, sock_path, sizeof(addr.sun_path) ); + addr.sun_family = AF_UNIX; + + if ( bind( sd, (struct sockaddr *)&addr, strlen(addr.sun_path)+sizeof(addr.sun_family)) < 0 ) + { + Error( "Can't bind: %s", strerror(errno) ); + exit( -1 ); + } + + if ( listen( sd, SOMAXCONN ) < 0 ) + { + Error( "Can't listen: %s", strerror(errno) ); + return( -1 ); + } + + struct sockaddr_un rem_addr; + socklen_t rem_addr_len = sizeof(rem_addr); + int new_sd = -1; + if ( (new_sd = accept( sd, (struct sockaddr *)&rem_addr, &rem_addr_len )) < 0 ) + { + Error( "Can't accept: %s", strerror(errno) ); + exit( -1 ); + } + close( sd ); + + sd = new_sd; + + Info( "Frame server socket open, awaiting images" ); + return( sd ); +} + +int ReopenSocket( int &sd, int monitor_id ) +{ + close( sd ); + return( sd = OpenSocket( monitor_id ) ); +} + +void Usage() +{ + fprintf( stderr, "zmf -m \n" ); + fprintf( stderr, "Options:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to use\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + exit( 0 ); +} + +int main( int argc, char *argv[] ) +{ + srand( getpid() * time( 0 ) ); + + int id = -1; + + static struct option long_options[] = { + {"monitor", 1, 0, 'm'}, + {"help", 0, 0, 'h'}, + {0, 0, 0, 0} + }; + + while (1) + { + int option_index = 0; + + int c = getopt_long (argc, argv, "m:h", long_options, &option_index); + if (c == -1) + { + break; + } + + switch (c) + { + case 'm': + id = atoi(optarg); + break; + case 'h': + case '?': + Usage(); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } + + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + Usage(); + } + + if ( id < 0 ) + { + fprintf( stderr, "Bogus monitor %d\n", id ); + Usage(); + exit( 0 ); + } + + char log_id_string[16]; + snprintf( log_id_string, sizeof(log_id_string), "m%d", id ); + + zmLoadConfig(); + + logInit( "zmf" ); + + ssedetect(); + + Monitor *monitor = Monitor::Load( id, false, Monitor::QUERY ); + + if ( !monitor ) + { + fprintf( stderr, "Can't find monitor with id of %d\n", id ); + exit( -1 ); + } + + char capt_path[PATH_MAX]; + char anal_path[PATH_MAX]; + snprintf( capt_path, sizeof(capt_path), "%s/%d/%%s/%%0%dd-capture.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); + snprintf( anal_path, sizeof(anal_path), "%s/%d/%%s/%%0%dd-analyse.jpg", config.dir_events, monitor->Id(), config.event_image_digits ); + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); + + sigset_t block_set; + sigemptyset( &block_set ); + + int sd = OpenSocket( monitor->Id() ); + + FrameHeader frame_header = { 0, 0, false, 0 }; + //unsigned char *image_data = 0; + + fd_set rfds; + + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + while( 1 ) + { + struct timeval temp_timeout = timeout; + + FD_ZERO(&rfds); + FD_SET(sd, &rfds); + int n_found = select( sd+1, &rfds, NULL, NULL, &temp_timeout ); + if( n_found == 0 ) + { + Debug( 1, "Select timed out" ); + continue; + } + else if ( n_found < 0) + { + Error( "Select error: %s", strerror(errno) ); + ReopenSocket( sd, monitor->Id() ); + continue; + } + + sigprocmask( SIG_BLOCK, &block_set, 0 ); + + int n_bytes = read( sd, &frame_header, sizeof(frame_header) ); + if ( n_bytes != sizeof(frame_header) ) + { + if ( n_bytes < 0 ) + { + Error( "Can't read frame header: %s", strerror(errno) ); + } + else if ( n_bytes > 0 ) + { + Error( "Incomplete read of frame header, %d bytes only", n_bytes ); + } + else + { + Warning( "Socket closed at remote end" ); + } + ReopenSocket( sd, monitor->Id() ); + continue; + } + Debug( 1, "Read frame header, expecting %ld bytes of image", frame_header.image_length ); + static unsigned char image_data[ZM_MAX_IMAGE_SIZE]; + n_bytes = read( sd, image_data, frame_header.image_length ); + if ( n_bytes != (ssize_t)frame_header.image_length ) + { + if ( n_bytes < 0 ) + { + Error( "Can't read frame image data: %s", strerror(errno) ); + } + else if ( n_bytes > 0 ) + { + Error( "Incomplete read of frame image data, %d bytes only", n_bytes ); + } + else + { + Warning( "Socket closed at remote end" ); + } + ReopenSocket( sd, monitor->Id() ); + continue; + } + static char subpath[PATH_MAX] = ""; + if ( config.use_deep_storage ) + { + struct tm *time = localtime( &frame_header.event_time ); + snprintf( subpath, sizeof(subpath), "%02d/%02d/%02d/%02d/%02d/%02d", time->tm_year-100, time->tm_mon+1, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec ); + } + else + { + snprintf( subpath, sizeof(subpath), "%ld", frame_header.event_id ); + } + static char path[PATH_MAX] = ""; + snprintf( path, sizeof(path), frame_header.alarm_frame?anal_path:capt_path, subpath, frame_header.frame_id ); + Debug( 1, "Got image, writing to %s", path ); + + FILE *fd = 0; + if ( (fd = fopen( path, "w" )) < 0 ) + { + Error( "Can't fopen '%s': %s", path, strerror(errno) ); + exit( -1 ); + } + if ( 0 == fwrite( image_data, frame_header.image_length, 1, fd ) ) + { + Error( "Can't fwrite image data: %s", strerror(errno) ); + exit( -1 ); + } + fclose( fd ); + + sigprocmask( SIG_UNBLOCK, &block_set, 0 ); + } +} diff --git a/src/zmf.h b/src/zmf.h new file mode 100644 index 000000000..f00ffa891 --- /dev/null +++ b/src/zmf.h @@ -0,0 +1,32 @@ +// +// ZoneMinder Image File Write Class Interface, $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. +// + +#ifndef ZMFILE_H +#define ZMFILE_H + +struct FrameHeader +{ + unsigned long event_id; + time_t event_time; + unsigned long frame_id; + bool alarm_frame; + unsigned long image_length; +}; + +#endif // ZMFILE_H diff --git a/src/zmfix.cpp b/src/zmfix.cpp new file mode 100644 index 000000000..2d3be8756 --- /dev/null +++ b/src/zmfix.cpp @@ -0,0 +1,205 @@ +// +// ZoneMinder Video Device Fixer, $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. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zm.h" +#include "zm_db.h" + +// Determine if we are a member of the group +int inGroup( gid_t gid ) +{ + // Get how many groups we are in + int n_gids = getgroups( 0, NULL ); + if ( n_gids < 0 ) + { + Error( "getgroups:%s", strerror(errno) ); + return( -1 ); + } + + // Not in any groups + if ( !n_gids ) + { + return( 0 ); + } + + // Allocate space to hold groups + gid_t *gids = new gid_t[n_gids * sizeof(gid_t)]; + if ( !gids ) + { + Error( "Unable to allocate groups: %s", strerror(errno) ); + return( -1 ); + } + + // Get list of groups + if ( getgroups( n_gids, gids ) != n_gids ) + { + Error( "getgroups:%s", strerror(errno) ); + delete[] gids; + return( -1 ); + } + + // See if gid in list of groups we belong to + int in_gid = 0; + for ( int i = 0; i < n_gids; i++ ) + { + if ( gids[i] == gid ) + { + in_gid = 1; + } + } + delete[] gids; + return( in_gid ); +} + +bool fixDevice( const char *device_path ) +{ + struct stat stat_buf; + + if ( stat( device_path, &stat_buf ) < 0 ) + { + Error( "Can't stat %s: %s", device_path, strerror(errno)); + return( false ); + } + + uid_t uid = getuid(); + gid_t gid = getgid(); + + int in_gid; + if ( (in_gid = inGroup( stat_buf.st_gid )) < 0 ) + { + return( false ); + } + + mode_t mask = 0; + if ( uid == stat_buf.st_uid ) + { + // If we are the owner + mask = 00600; + } + else if ( gid == stat_buf.st_gid || in_gid ) + { + // If we are in the owner group + mask = 00060; + } + else + { + // We are neither the owner nor in the group + mask = 00006; + } + + mode_t mode = stat_buf.st_mode; + if ( (mode & mask) == mask ) + { + Debug( 1, "Permissions on %s are ok at %o", device_path, mode ); + return( true ); + } + mode |= mask; + + Info( "Resetting permissions on %s to %o", device_path, mode ); + if ( chmod( device_path, mode ) < 0 ) + { + Error( "Can't chmod %s to %o: %s", device_path, mode, strerror(errno)); + return( false ); + } + return( true ); +} + +int main( int argc, char *argv[] ) +{ + zmLoadConfig(); + + logInit( "zmfix" ); + logCapLevel( Logger::ERROR ); + + // Only do registered devices + static char sql[ZM_SQL_SML_BUFSIZ]; + snprintf( sql, sizeof(sql), "select distinct Device from Monitors where not isnull(Device) and Type = 'Local'" ); + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + fixDevice( dbrow[0] ); + } + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + snprintf( sql, sizeof(sql), "select distinct ControlDevice from Monitors where not isnull(ControlDevice)" ); + if ( mysql_query( &dbconn, sql ) ) + { + Error( "Can't run query: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + result = mysql_store_result( &dbconn ); + if ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + fixDevice( dbrow[0] ); + } + + if ( mysql_errno( &dbconn ) ) + { + Error( "Can't fetch row: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + // Yadda yadda + mysql_free_result( result ); + + if ( config.opt_x10 ) + { + if ( config.x10_device ) + { + fixDevice( config.x10_device ); + } + } + + return( 0 ); +} diff --git a/src/zms.cpp b/src/zms.cpp new file mode 100644 index 000000000..af294cb71 --- /dev/null +++ b/src/zms.cpp @@ -0,0 +1,327 @@ +// +// ZoneMinder Streaming Server, $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. +// + +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_user.h" +#include "zm_signal.h" +#include "zm_monitor.h" + +bool ValidateAccess( User *user, int mon_id ) +{ + bool allowed = true; + + if ( mon_id > 0 ) + { + if ( user->getStream() < User::PERM_VIEW ) + allowed = false; + if ( !user->canAccess( mon_id ) ) + allowed = false; + } + else + { + if ( user->getEvents() < User::PERM_VIEW ) + allowed = false; + } + if ( !allowed ) + { + Error( "Error, insufficient privileges for requested action" ); + exit( -1 ); + } + return( allowed ); +} + +int main( int argc, const char *argv[] ) +{ + srand( getpid() * time( 0 ) ); + + enum { ZMS_MONITOR, ZMS_EVENT } source = ZMS_MONITOR; + enum { ZMS_JPEG, ZMS_MPEG, ZMS_RAW, ZMS_ZIP, ZMS_SINGLE } mode = ZMS_JPEG; + char format[32] = ""; + int monitor_id = 0; + time_t event_time = 0; + int event_id = 0; + int frame_id = 1; + unsigned int scale = 100; + unsigned int rate = 100; + double maxfps = 10.0; + unsigned int bitrate = 100000; + unsigned int ttl = 0; + EventStream::StreamMode replay = EventStream::MODE_SINGLE; + char username[64] = ""; + char password[64] = ""; + char auth[64] = ""; + unsigned int connkey = 0; + unsigned int playback_buffer = 0; + + bool nph = false; + const char *basename = strrchr( argv[0], '/' ); + if (basename) //if we found a / lets skip past it + basename++; + else //argv[0] will not always contain the full path, but rather just the script name + basename = argv[0]; + const char *nph_prefix = "nph-"; + if ( basename && !strncmp( basename, nph_prefix, strlen(nph_prefix) ) ) + { + nph = true; + } + + zmLoadConfig(); + + logInit( "zms" ); + + ssedetect(); + + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); + + const char *query = getenv( "QUERY_STRING" ); + if ( query ) + { + Debug( 1, "Query: %s", query ); + + char temp_query[1024]; + strncpy( temp_query, query, sizeof(temp_query) ); + char *q_ptr = temp_query; + char *parms[16]; // Shouldn't be more than this + int parm_no = 0; + while( (parm_no < 16) && (parms[parm_no] = strtok( q_ptr, "&" )) ) + { + parm_no++; + q_ptr = NULL; + } + + for ( int p = 0; p < parm_no; p++ ) + { + char *name = strtok( parms[p], "=" ); + char *value = strtok( NULL, "=" ); + if ( !value ) + value = (char *)""; + if ( !strcmp( name, "source" ) ) + { + source = !strcmp( value, "event" )?ZMS_EVENT:ZMS_MONITOR; + } + else if ( !strcmp( name, "mode" ) ) + { + mode = !strcmp( value, "jpeg" )?ZMS_JPEG:ZMS_MPEG; + mode = !strcmp( value, "raw" )?ZMS_RAW:mode; + mode = !strcmp( value, "zip" )?ZMS_ZIP:mode; + mode = !strcmp( value, "single" )?ZMS_SINGLE:mode; + } + else if ( !strcmp( name, "format" ) ) + strncpy( format, value, sizeof(format) ); + else if ( !strcmp( name, "monitor" ) ) + monitor_id = atoi( value ); + else if ( !strcmp( name, "time" ) ) + event_time = atoi( value ); + else if ( !strcmp( name, "event" ) ) + event_id = strtoull( value, (char **)NULL, 10 ); + else if ( !strcmp( name, "frame" ) ) + frame_id = strtoull( value, (char **)NULL, 10 ); + else if ( !strcmp( name, "scale" ) ) + scale = atoi( value ); + else if ( !strcmp( name, "rate" ) ) + rate = atoi( value ); + else if ( !strcmp( name, "maxfps" ) ) + maxfps = atof( value ); + else if ( !strcmp( name, "bitrate" ) ) + bitrate = atoi( value ); + else if ( !strcmp( name, "ttl" ) ) + ttl = atoi(value); + else if ( !strcmp( name, "replay" ) ) + { + replay = !strcmp( value, "gapless" )?EventStream::MODE_ALL_GAPLESS:EventStream::MODE_SINGLE; + replay = !strcmp( value, "all" )?EventStream::MODE_ALL:replay; + } + else if ( !strcmp( name, "connkey" ) ) + connkey = atoi(value); + else if ( !strcmp( name, "buffer" ) ) + playback_buffer = atoi(value); + else if ( config.opt_use_auth ) + { + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( !strcmp( name, "user" ) ) + { + strncpy( username, value, sizeof(username) ); + } + } + else + { + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( !strcmp( name, "auth" ) ) + { + strncpy( auth, value, sizeof(auth) ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( !strcmp( name, "user" ) ) + { + strncpy( username, value, sizeof(username) ); + } + if ( !strcmp( name, "pass" ) ) + { + strncpy( password, value, sizeof(password) ); + } + } + } + } + } + } + + if ( config.opt_use_auth ) + { + User *user = 0; + + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( *username ) + { + user = zmLoadUser( username ); + } + } + else + { + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( *auth ) + { + user = zmLoadAuthUser( auth, config.auth_hash_ips ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( *username && *password ) + { + user = zmLoadUser( username, password ); + } + } + } + if ( !user ) + { + Error( "Unable to authenticate user" ); + return( -1 ); + } + ValidateAccess( user, monitor_id ); + } + + setbuf( stdout, 0 ); + if ( nph ) + { + fprintf( stdout, "HTTP/1.0 200 OK\r\n" ); + } + fprintf( stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION ); + + time_t now = time( 0 ); + char date_string[64]; + strftime( date_string, sizeof(date_string)-1, "%a, %d %b %Y %H:%M:%S GMT", gmtime( &now ) ); + + fprintf( stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n" ); + fprintf( stdout, "Last-Modified: %s\r\n", date_string ); + fprintf( stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n" ); + fprintf( stdout, "Cache-Control: post-check=0, pre-check=0\r\n" ); + fprintf( stdout, "Pragma: no-cache\r\n"); + // Removed as causing more problems than it fixed. + //if ( !nph ) + //{ + //fprintf( stdout, "Content-Length: 0\r\n"); + //} + + if ( source == ZMS_MONITOR ) + { + MonitorStream stream; + stream.setStreamScale( scale ); + stream.setStreamReplayRate( rate ); + stream.setStreamMaxFPS( maxfps ); + stream.setStreamTTL( ttl ); + stream.setStreamQueue( connkey ); + stream.setStreamBuffer( playback_buffer ); + stream.setStreamStart( monitor_id ); + + if ( mode == ZMS_JPEG ) + { + stream.setStreamType( MonitorStream::STREAM_JPEG ); + } + else if ( mode == ZMS_RAW ) + { + stream.setStreamType( MonitorStream::STREAM_RAW ); + } + else if ( mode == ZMS_ZIP ) + { + stream.setStreamType( MonitorStream::STREAM_ZIP ); + } + else if ( mode == ZMS_SINGLE ) + { + stream.setStreamType( MonitorStream::STREAM_SINGLE ); + } + else + { +#if HAVE_LIBAVCODEC + stream.setStreamFormat( format ); + stream.setStreamBitrate( bitrate ); + stream.setStreamType( MonitorStream::STREAM_MPEG ); +#else // HAVE_LIBAVCODEC + Error( "MPEG streaming of '%s' attempted while disabled", query ); + fprintf( stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n" ); + return( -1 ); +#endif // HAVE_LIBAVCODEC + } + stream.runStream(); + } + else if ( source == ZMS_EVENT ) + { + EventStream stream; + stream.setStreamScale( scale ); + stream.setStreamReplayRate( rate ); + stream.setStreamMaxFPS( maxfps ); + stream.setStreamMode( replay ); + stream.setStreamQueue( connkey ); + if ( monitor_id && event_time ) + { + stream.setStreamStart( monitor_id, event_time ); + } + else + { + stream.setStreamStart( event_id, frame_id ); + } + if ( mode == ZMS_JPEG ) + { + stream.setStreamType( EventStream::STREAM_JPEG ); + } + else + { +#if HAVE_LIBAVCODEC + stream.setStreamFormat( format ); + stream.setStreamBitrate( bitrate ); + stream.setStreamType( EventStream::STREAM_MPEG ); +#else // HAVE_LIBAVCODEC + Error( "MPEG streaming of '%s' attempted while disabled", query ); + fprintf( stderr, "MPEG streaming is disabled.\nYou should ensure the ffmpeg libraries are installed and detected and rebuild to use this functionality.\n" ); + return( -1 ); +#endif // HAVE_LIBAVCODEC + } + stream.runStream(); + } + return( 0 ); +} diff --git a/src/zmstreamer.cpp b/src/zmstreamer.cpp new file mode 100644 index 000000000..26384412a --- /dev/null +++ b/src/zmstreamer.cpp @@ -0,0 +1,195 @@ +// +// ZoneMinder Streamer, $Date: 2010-10-14 23:21:00 +0200 (Thu, 14 Oct 2010) $ +// Copyright (C) 2001-2010 Philip Coombes, Chris Kistner +// +// This program is based on revision 3143 of +// http://svn.zoneminder.com/svn/zm/trunk/src/zms.cpp +// +// 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. + +#include +#include + +#include +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_user.h" +#include "zm_signal.h" +#include "zm_monitor.h" +#include "zm_stream.h" + +// Possible command-line options +#define OPTIONS "e:o:u:f:s:b:m:d:i:?" + +// Default ZMS values +#define ZMS_DEFAULT_DEBUG 0 +#define ZMS_DEFAULT_ID 1 +#define ZMS_DEFAULT_BITRATE 100000 +#define ZMS_DEFAULT_SCALE 100 +#define ZMS_DEFAULT_MODE "mpeg" +#define ZMS_DEFAULT_FORMAT "asf" +#define ZMS_DEFAULT_FPS 25.0 +#define ZMS_DEFAULT_BUFFER 1000 + +int main(int argc, char** argv) { + // Set initial values to the default values + int debug = ZMS_DEFAULT_DEBUG; + int id = ZMS_DEFAULT_ID; + int bitrate = ZMS_DEFAULT_BITRATE; + int scale = ZMS_DEFAULT_SCALE; + char mode[32]; + sprintf(mode, "%s", ZMS_DEFAULT_MODE); + char format[32]; + sprintf(format, "%s", ZMS_DEFAULT_FORMAT); + double maxfps = ZMS_DEFAULT_FPS; + int buffer = ZMS_DEFAULT_BUFFER; + + // Parse command-line options + int arg; + while ((arg = getopt(argc, argv, OPTIONS)) != -1) { + switch (arg) { + case 'e': + sprintf(mode, "%s", optarg); + break; + case 'o': + sprintf(format, "%s", optarg); + break; + case 'u': + buffer = atoi(optarg); + break; + case 'f': + maxfps = atof(optarg); + break; + case 's': + scale = atoi(optarg); + break; + case 'b': + bitrate = atoi(optarg); + break; + case 'm': + id = atoi(optarg); + break; + case 'd': + debug = atoi(optarg); + break; + case 'i': + case '?': + printf("-e : Specify output mode: mpeg/jpg/zip/single/raw. Default = %s\n", ZMS_DEFAULT_MODE); + printf("-o : Specify output format. Default = %s\n", ZMS_DEFAULT_FORMAT); + printf("-u : Specify buffer size in ms. Default = %d\n", ZMS_DEFAULT_BUFFER); + printf("-f : Specify maximum framerate. Default = %lf\n", ZMS_DEFAULT_FPS); + printf("-s : Specify scale. Default = %d\n", ZMS_DEFAULT_SCALE); + printf("-b : Specify bitrate. Default = %d\n", ZMS_DEFAULT_BITRATE); + printf("-m : Specify monitor id. Default = %d\n", ZMS_DEFAULT_ID); + printf("-d : 0 = off, 1 = no streaming, 2 = with streaming. Default = 0\n"); + printf("-i or -? : This information\n"); + return EXIT_SUCCESS; + } + } + + // Set stream type + StreamBase::StreamType streamtype; + if (!strcasecmp("raw", mode)) + streamtype = MonitorStream::STREAM_RAW; + else if (!strcasecmp("mpeg", mode)) + streamtype = MonitorStream::STREAM_MPEG; + else if (!strcasecmp("jpg", mode)) + streamtype = MonitorStream::STREAM_JPEG; + else if (!strcasecmp("single", mode)) + streamtype = MonitorStream::STREAM_SINGLE; + else if (!strcasecmp("zip", mode)) + streamtype = MonitorStream::STREAM_ZIP; + else + streamtype = MonitorStream::STREAM_MPEG; + + if (debug) { + // Show stream parameters + printf("Stream parameters:\n"); + switch (streamtype) { + case MonitorStream::STREAM_MPEG: + printf("Output mode (-e) = %s\n", "mpeg"); + printf("Output format (-o) = %s\n", format); + break; + default: + printf("Output mode (-e) = %s\n", mode); + } + printf("Buffer size (-u) = %d ms\n", buffer); + printf("Maximum FPS (-f) = %lf FPS\n", maxfps); + printf("Scale (-s) = %d%%\n", scale); + printf("Bitrate (-b) = %d bps\n", bitrate); + printf("Monitor Id (-m) = %d\n", id); + } + + if (debug) { + // Set ZM debugger to print to stdout + printf("Setting up ZoneMinder debugger to print to stdout..."); + setenv("ZM_DBG_PRINT", "1", 1); + printf("Done.\n"); + } + + // Loading ZM configurations + printf("Loading ZoneMinder configurations..."); + zmLoadConfig(); + printf("Done.\n"); + + logInit("zmstreamer"); + + ssedetect(); + + // Setting stream parameters + MonitorStream stream; + stream.setStreamScale(scale); // default = 100 (scale) + stream.setStreamReplayRate(100); // default = 100 (rate) + stream.setStreamMaxFPS(maxfps); // default = 10 (maxfps) + if (debug) stream.setStreamTTL(1); + else stream.setStreamTTL(0); // default = 0 (ttl) + stream.setStreamQueue(0); // default = 0 (connkey) + stream.setStreamBuffer(buffer); // default = 0 (buffer) + stream.setStreamStart(id); // default = 0 (monitor_id) + stream.setStreamType(streamtype); + if (streamtype == MonitorStream::STREAM_MPEG) { +#if HAVE_LIBAVCODEC + if (debug) printf("HAVE_LIBAVCODEC is set\n"); + stream.setStreamFormat(format); // default = "" (format) + stream.setStreamBitrate(bitrate); // default = 100000 (bitrate) +#else + fprintf(stderr, "MPEG streaming is disabled.\nYou should configure with the --with-ffmpeg option and rebuild to use this functionality.\n"); + return EXIT_FAILURE; +#endif + } + + if (debug != 1) { + if (debug) printf("Running stream..."); + + // Output headers + fprintf(stdout, "Server: ZoneMinder Video Server/%s\r\n", ZM_VERSION); + time_t now = time(0); + char date_string[64]; + strftime(date_string, sizeof (date_string) - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&now)); + fprintf(stdout, "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"); + fprintf(stdout, "Last-Modified: %s\r\n", date_string); + fprintf(stdout, "Cache-Control: no-store, no-cache, must-revalidate\r\n"); + fprintf(stdout, "Cache-Control: post-check=0, pre-check=0\r\n"); + fprintf(stdout, "Pragma: no-cache\r\n"); + + // Run stream + stream.runStream(); + } + if (debug) printf("Done.\n"); + + return (EXIT_SUCCESS); +} diff --git a/src/zmu.cpp b/src/zmu.cpp new file mode 100644 index 000000000..49efafd05 --- /dev/null +++ b/src/zmu.cpp @@ -0,0 +1,751 @@ +// +// ZoneMinder Control Utility, $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. +// + +#include + +#include "zm.h" +#include "zm_db.h" +#include "zm_user.h" +#include "zm_signal.h" +#include "zm_monitor.h" +#include "zm_local_camera.h" + +void Usage( int status=-1 ) +{ + fprintf( stderr, "zmu <-d device_path> [-v] [function] [-U -P]\n" ); + fprintf( stderr, "zmu <-m monitor_id> [-v] [function] [-U -P]\n" ); + fprintf( stderr, "General options:\n" ); + fprintf( stderr, " -h, --help : This screen\n" ); + fprintf( stderr, " -v, --verbose : Produce more verbose output\n" ); + fprintf( stderr, " -l, --list : List the current status of active (or all with -v) monitors\n" ); + fprintf( stderr, "Options for use with devices:\n" ); + fprintf( stderr, " -d, --device [device_path] : Get the current video device settings for [device_path] or all devices\n" ); + fprintf( stderr, " -V, --version : Set the Video 4 Linux API version to use for the query, use 1 or 2\n" ); + fprintf( stderr, " -q, --query : Query the current settings for the device\n" ); + fprintf( stderr, "Options for use with monitors:\n" ); + fprintf( stderr, " -m, --monitor : Specify which monitor to address, default 1 if absent\n" ); + fprintf( stderr, " -q, --query : Query the current settings for the monitor\n" ); + fprintf( stderr, " -s, --state : Output the current monitor state, 0 = idle, 1 = prealarm, 2 = alarm,\n" ); + fprintf( stderr, " 3 = alert, 4 = tape\n" ); + fprintf( stderr, " -B, --brightness [value] : Output the current brightness, set to value if given \n" ); + fprintf( stderr, " -C, --contrast [value] : Output the current contrast, set to value if given \n" ); + fprintf( stderr, " -H, --hue [value] : Output the current hue, set to value if given \n" ); + fprintf( stderr, " -O, --colour [value] : Output the current colour, set to value if given \n" ); + fprintf( stderr, " -i, --image [image_index] : Write captured image to disk as .jpg, last image captured\n" ); + fprintf( stderr, " or specified ring buffer index if given.\n" ); + fprintf( stderr, " -S, --scale : With --image specify any scaling (in %%) to be applied to the image\n" ); + fprintf( stderr, " -t, --timestamp [image_index] : Output captured image timestamp, last image captured or specified\n" ); + fprintf( stderr, " ring buffer index if given\n" ); + fprintf( stderr, " -R, --read_index : Output ring buffer read index\n" ); + fprintf( stderr, " -W, --write_index : Output ring buffer write index\n" ); + fprintf( stderr, " -e, --event : Output last event index\n" ); + fprintf( stderr, " -f, --fps : Output last Frames Per Second captured reading\n" ); + fprintf( stderr, " -z, --zones : Write last captured image overlaid with zones to -Zones.jpg\n" ); + fprintf( stderr, " -a, --alarm : Force alarm in monitor, this will trigger recording until cancelled with -c\n" ); + fprintf( stderr, " -n, --noalarm : Force no alarms in monitor, this will prevent alarms until cancelled with -c\n" ); + fprintf( stderr, " -c, --cancel : Cancel a forced alarm/noalarm in monitor, required after being enabled with -a or -n\n" ); + fprintf( stderr, " -L, --reload : Signal monitor to reload settings\n" ); + fprintf( stderr, " -E, --enable : Enable detection, wake monitor up\n" ); + fprintf( stderr, " -D, --disable : Disable detection, put monitor to sleep\n" ); + fprintf( stderr, " -u, --suspend : Suspend detection, useful to prevent bogus alarms when panning etc\n" ); + fprintf( stderr, " -r, --resume : Resume detection after a suspend\n" ); + fprintf( stderr, " -U, --username : When running in authenticated mode the username and\n" ); + fprintf( stderr, " -P, --password : password combination of the given user\n" ); + fprintf( stderr, " -A, --auth : Pass authentication hash string instead of user details\n" ); + + exit( status ); +} + +typedef enum { + ZMU_BOGUS = 0x00000000, + ZMU_STATE = 0x00000001, + ZMU_IMAGE = 0x00000002, + ZMU_TIME = 0x00000004, + ZMU_READ_IDX = 0x00000008, + ZMU_WRITE_IDX = 0x00000010, + ZMU_EVENT = 0x00000020, + ZMU_FPS = 0x00000040, + ZMU_ZONES = 0x00000080, + ZMU_ALARM = 0x00000100, + ZMU_NOALARM = 0x00000200, + ZMU_CANCEL = 0x00000400, + ZMU_QUERY = 0x00000800, + ZMU_BRIGHTNESS = 0x00001000, + ZMU_CONTRAST = 0x00002000, + ZMU_HUE = 0x00004000, + ZMU_COLOUR = 0x00008000, + ZMU_RELOAD = 0x00010000, + ZMU_ENABLE = 0x00100000, + ZMU_DISABLE = 0x00200000, + ZMU_SUSPEND = 0x00400000, + ZMU_RESUME = 0x00800000, + ZMU_LIST = 0x10000000, +} Function; + +bool ValidateAccess( User *user, int mon_id, int function ) +{ + bool allowed = true; + if ( function & (ZMU_STATE|ZMU_IMAGE|ZMU_TIME|ZMU_READ_IDX|ZMU_WRITE_IDX|ZMU_FPS) ) + { + if ( user->getStream() < User::PERM_VIEW ) + allowed = false; + } + if ( function & ZMU_EVENT ) + { + if ( user->getEvents() < User::PERM_VIEW ) + allowed = false; + } + if ( function & (ZMU_ZONES|ZMU_QUERY|ZMU_LIST) ) + { + if ( user->getMonitors() < User::PERM_VIEW ) + allowed = false; + } + if ( function & (ZMU_ALARM|ZMU_NOALARM|ZMU_CANCEL|ZMU_RELOAD|ZMU_ENABLE|ZMU_DISABLE|ZMU_SUSPEND|ZMU_RESUME|ZMU_BRIGHTNESS|ZMU_CONTRAST|ZMU_HUE|ZMU_COLOUR) ) + { + if ( user->getMonitors() < User::PERM_EDIT ) + allowed = false; + } + if ( mon_id > 0 ) + { + if ( !user->canAccess( mon_id ) ) + { + allowed = false; + } + } + if ( !allowed ) + { + fprintf( stderr, "Error, insufficient privileges for requested action\n" ); + exit( -1 ); + } + return( allowed ); +} + +int main( int argc, char *argv[] ) +{ + srand( getpid() * time( 0 ) ); + + static struct option long_options[] = { + {"device", 2, 0, 'd'}, + {"monitor", 1, 0, 'm'}, + {"verbose", 0, 0, 'v'}, + {"image", 2, 0, 'i'}, + {"scale", 1, 0, 'S'}, + {"timestamp", 2, 0, 't'}, + {"state", 0, 0, 's'}, + {"brightness", 2, 0, 'B'}, + {"contrast", 2, 0, 'C'}, + {"hue", 2, 0, 'H'}, + {"contrast", 2, 0, 'O'}, + {"read_index", 0, 0, 'R'}, + {"write_index", 0, 0, 'W'}, + {"event", 0, 0, 'e'}, + {"fps", 0, 0, 'f'}, + {"zones", 2, 0, 'z'}, + {"alarm", 0, 0, 'a'}, + {"noalarm", 0, 0, 'n'}, + {"cancel", 0, 0, 'c'}, + {"reload", 0, 0, 'L'}, + {"enable", 0, 0, 'E'}, + {"disable", 0, 0, 'D'}, + {"suspend", 0, 0, 'u'}, + {"resume", 0, 0, 'r'}, + {"query", 0, 0, 'q'}, + {"username", 1, 0, 'U'}, + {"password", 1, 0, 'P'}, + {"auth", 1, 0, 'A'}, + {"version", 1, 0, 'V'}, + {"help", 0, 0, 'h'}, + {"list", 0, 0, 'l'}, + {0, 0, 0, 0} + }; + + const char *device = 0; + int mon_id = 0; + bool verbose = false; + int function = ZMU_BOGUS; + + int image_idx = -1; + int scale = -1; + int brightness = -1; + int contrast = -1; + int hue = -1; + int colour = -1; + char *zoneString = 0; + char *username = 0; + char *password = 0; + char *auth = 0; +#if ZM_HAS_V4L +#if ZM_HAS_V4L2 + int v4lVersion = 2; +#elif ZM_HAS_V4L1 + int v4lVersion = 1; +#endif // ZM_HAS_V4L2/1 +#endif // ZM_HAS_V4L + while (1) + { + int option_index = 0; + + int c = getopt_long (argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::U:P:A:V:", long_options, &option_index); + if (c == -1) + { + break; + } + + switch (c) + { + case 'd': + if ( optarg ) + device = optarg; + break; + case 'm': + mon_id = atoi(optarg); + break; + case 'v': + verbose = true; + break; + case 's': + function |= ZMU_STATE; + break; + case 'i': + function |= ZMU_IMAGE; + if ( optarg ) + image_idx = atoi( optarg ); + break; + case 'S': + scale = atoi(optarg); + break; + case 't': + function |= ZMU_TIME; + if ( optarg ) + image_idx = atoi( optarg ); + break; + case 'R': + function |= ZMU_READ_IDX; + break; + case 'W': + function |= ZMU_WRITE_IDX; + break; + case 'e': + function |= ZMU_EVENT; + break; + case 'f': + function |= ZMU_FPS; + break; + case 'z': + function |= ZMU_ZONES; + if ( optarg ) + zoneString = optarg; + break; + case 'a': + function |= ZMU_ALARM; + break; + case 'n': + function |= ZMU_NOALARM; + break; + case 'c': + function |= ZMU_CANCEL; + break; + case 'L': + function |= ZMU_RELOAD; + break; + case 'E': + function |= ZMU_ENABLE; + break; + case 'D': + function |= ZMU_DISABLE; + break; + case 'u': + function |= ZMU_SUSPEND; + break; + case 'r': + function |= ZMU_RESUME; + break; + case 'q': + function |= ZMU_QUERY; + break; + case 'B': + function |= ZMU_BRIGHTNESS; + if ( optarg ) + brightness = atoi( optarg ); + break; + case 'C': + function |= ZMU_CONTRAST; + if ( optarg ) + contrast = atoi( optarg ); + break; + case 'H': + function |= ZMU_HUE; + if ( optarg ) + hue = atoi( optarg ); + break; + case 'O': + function |= ZMU_COLOUR; + if ( optarg ) + colour = atoi( optarg ); + break; + case 'U': + username = optarg; + break; + case 'P': + password = optarg; + break; + case 'A': + auth = optarg; + break; +#if ZM_HAS_V4L + case 'V': + v4lVersion = (atoi(optarg)==1)?1:2; + break; +#endif // ZM_HAS_V4L + case 'h': + Usage( 0 ); + break; + case 'l': + function |= ZMU_LIST; + break; + case '?': + Usage(); + break; + default: + //fprintf( stderr, "?? getopt returned character code 0%o ??\n", c ); + break; + } + } + + if (optind < argc) + { + fprintf( stderr, "Extraneous options, " ); + while (optind < argc) + fprintf( stderr, "%s ", argv[optind++]); + fprintf( stderr, "\n"); + Usage(); + } + + if ( device && !(function&ZMU_QUERY) ) + { + fprintf( stderr, "Error, -d option cannot be used with this option\n" ); + Usage(); + } + if ( scale != -1 && !(function&ZMU_IMAGE) ) + { + fprintf( stderr, "Error, -S option cannot be used with this option\n" ); + Usage(); + } + //printf( "Monitor %d, Function %d\n", mon_id, function ); + + zmLoadConfig(); + + logInit( "zmu" ); + + zmSetDefaultTermHandler(); + zmSetDefaultDieHandler(); + + User *user = 0; + + if ( config.opt_use_auth ) + { + if ( strcmp( config.auth_relay, "none" ) == 0 ) + { + if ( !username ) + { + fprintf( stderr, "Error, username must be supplied\n" ); + exit( -1 ); + } + + if ( username ) + { + user = zmLoadUser( username ); + } + } + else + { + if ( !(username && password) && !auth ) + { + fprintf( stderr, "Error, username and password or auth string must be supplied\n" ); + exit( -1 ); + } + + //if ( strcmp( config.auth_relay, "hashed" ) == 0 ) + { + if ( auth ) + { + user = zmLoadAuthUser( auth, false ); + } + } + //else if ( strcmp( config.auth_relay, "plain" ) == 0 ) + { + if ( username && password ) + { + user = zmLoadUser( username, password ); + } + } + } + if ( !user ) + { + fprintf( stderr, "Error, unable to authenticate user\n" ); + exit( -1 ); + } + ValidateAccess( user, mon_id, function ); + } + + + if ( mon_id > 0 ) + { + Monitor *monitor = Monitor::Load( mon_id, function&(ZMU_QUERY|ZMU_ZONES), Monitor::QUERY ); + if ( monitor ) + { + if ( verbose ) + { + printf( "Monitor %d(%s)\n", monitor->Id(), monitor->Name() ); + } + char separator = ' '; + bool have_output = false; + if ( function & ZMU_STATE ) + { + Monitor::State state = monitor->GetState(); + if ( verbose ) + printf( "Current state: %s\n", state==Monitor::ALARM?"Alarm":(state==Monitor::ALERT?"Alert":"Idle") ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", state ); + have_output = true; + } + } + if ( function & ZMU_TIME ) + { + struct timeval timestamp = monitor->GetTimestamp( image_idx ); + if ( verbose ) + { + char timestamp_str[64] = "None"; + if ( timestamp.tv_sec ) + strftime( timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S", localtime( ×tamp.tv_sec ) ); + if ( image_idx == -1 ) + printf( "Time of last image capture: %s.%02ld\n", timestamp_str, timestamp.tv_usec/10000 ); + else + printf( "Time of image %d capture: %s.%02ld\n", image_idx, timestamp_str, timestamp.tv_usec/10000 ); + } + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%ld.%02ld", timestamp.tv_sec, timestamp.tv_usec/10000 ); + have_output = true; + } + } + if ( function & ZMU_READ_IDX ) + { + if ( verbose ) + printf( "Last read index: %d\n", monitor->GetLastReadIndex() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastReadIndex() ); + have_output = true; + } + } + if ( function & ZMU_WRITE_IDX ) + { + if ( verbose ) + printf( "Last write index: %d\n", monitor->GetLastWriteIndex() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastWriteIndex() ); + have_output = true; + } + } + if ( function & ZMU_EVENT ) + { + if ( verbose ) + printf( "Last event id: %d\n", monitor->GetLastEvent() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%d", monitor->GetLastEvent() ); + have_output = true; + } + } + if ( function & ZMU_FPS ) + { + if ( verbose ) + printf( "Current capture rate: %.2f frames per second\n", monitor->GetFPS() ); + else + { + if ( have_output ) printf( "%c", separator ); + printf( "%.2f", monitor->GetFPS() ); + have_output = true; + } + } + if ( function & ZMU_IMAGE ) + { + if ( verbose ) + { + if ( image_idx == -1 ) + printf( "Dumping last image captured to Monitor%d.jpg", monitor->Id() ); + else + printf( "Dumping buffer image %d to Monitor%d.jpg", image_idx, monitor->Id() ); + if ( scale != -1 ) + printf( ", scaling by %d%%", scale ); + printf( "\n" ); + } + monitor->GetImage( image_idx, scale>0?scale:100 ); + } + if ( function & ZMU_ZONES ) + { + if ( verbose ) + printf( "Dumping zone image to Zones%d.jpg\n", monitor->Id() ); + monitor->DumpZoneImage( zoneString ); + } + if ( function & ZMU_ALARM ) + { + if ( verbose ) + printf( "Forcing alarm on\n" ); + monitor->ForceAlarmOn( config.forced_alarm_score, "Forced Web" ); + } + if ( function & ZMU_NOALARM ) + { + if ( verbose ) + printf( "Forcing alarm off\n" ); + monitor->ForceAlarmOff(); + } + if ( function & ZMU_CANCEL ) + { + if ( verbose ) + printf( "Cancelling forced alarm on/off\n" ); + monitor->CancelForced(); + } + if ( function & ZMU_RELOAD ) + { + if ( verbose ) + printf( "Reloading monitor settings\n" ); + monitor->actionReload(); + } + if ( function & ZMU_ENABLE ) + { + if ( verbose ) + printf( "Enabling event generation\n" ); + monitor->actionEnable(); + } + if ( function & ZMU_DISABLE ) + { + if ( verbose ) + printf( "Disabling event generation\n" ); + monitor->actionDisable(); + } + if ( function & ZMU_SUSPEND ) + { + if ( verbose ) + printf( "Suspending event generation\n" ); + monitor->actionSuspend(); + } + if ( function & ZMU_RESUME ) + { + if ( verbose ) + printf( "Resuming event generation\n" ); + monitor->actionResume(); + } + if ( function & ZMU_QUERY ) + { + char monString[16382] = ""; + monitor->DumpSettings( monString, verbose ); + printf( "%s\n", monString ); + } + if ( function & ZMU_BRIGHTNESS ) + { + if ( verbose ) + { + if ( brightness >= 0 ) + printf( "New brightness: %d\n", monitor->actionBrightness( brightness ) ); + else + printf( "Current brightness: %d\n", monitor->actionBrightness() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( brightness >= 0 ) + printf( "%d", monitor->actionBrightness( brightness ) ); + else + printf( "%d", monitor->actionBrightness() ); + have_output = true; + } + } + if ( function & ZMU_CONTRAST ) + { + if ( verbose ) + { + if ( contrast >= 0 ) + printf( "New brightness: %d\n", monitor->actionContrast( contrast ) ); + else + printf( "Current contrast: %d\n", monitor->actionContrast() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( contrast >= 0 ) + printf( "%d", monitor->actionContrast( contrast ) ); + else + printf( "%d", monitor->actionContrast() ); + have_output = true; + } + } + if ( function & ZMU_HUE ) + { + if ( verbose ) + { + if ( hue >= 0 ) + printf( "New hue: %d\n", monitor->actionHue( hue ) ); + else + printf( "Current hue: %d\n", monitor->actionHue() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( hue >= 0 ) + printf( "%d", monitor->actionHue( hue ) ); + else + printf( "%d", monitor->actionHue() ); + have_output = true; + } + } + if ( function & ZMU_COLOUR ) + { + if ( verbose ) + { + if ( colour >= 0 ) + printf( "New colour: %d\n", monitor->actionColour( colour ) ); + else + printf( "Current colour: %d\n", monitor->actionColour() ); + } + else + { + if ( have_output ) printf( "%c", separator ); + if ( colour >= 0 ) + printf( "%d", monitor->actionColour( colour ) ); + else + printf( "%d", monitor->actionColour() ); + have_output = true; + } + } + if ( have_output ) + { + printf( "\n" ); + } + if ( !function ) + { + Usage(); + } + delete monitor; + } + else + { + fprintf( stderr, "Error, invalid monitor id %d\n", mon_id ); + exit( -1 ); + } + } + else + { + if ( function & ZMU_QUERY ) + { +#if ZM_HAS_V4L + char vidString[0x10000] = ""; + bool ok = LocalCamera::GetCurrentSettings( device, vidString, v4lVersion, verbose ); + printf( "%s", vidString ); + exit( ok?0:-1 ); +#else // ZM_HAS_V4L + fprintf( stderr, "Error, video4linux is required for device querying\n" ); + exit( -1 ); +#endif // ZM_HAS_V4L + } + + if ( function & ZMU_LIST ) + { + char sql[ZM_SQL_SML_BUFSIZ]; + strncpy( sql, "select Id, Function+0 from Monitors", sizeof(sql) ); + if ( !verbose ) + { + strncat( sql, " where Function != 'None'", sizeof(sql)-strlen(sql) ); + } + strncat( sql, " order by Id asc", sizeof(sql)-strlen(sql) ); + + 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 ( !result ) + { + Error( "Can't use query result: %s", mysql_error( &dbconn ) ); + exit( mysql_errno( &dbconn ) ); + } + int n_monitors = mysql_num_rows( result ); + Debug( 1, "Got %d monitors", n_monitors ); + + printf( "%4s%5s%6s%9s%14s%6s%6s%8s%8s\n", "Id", "Func", "State", "TrgState", "LastImgTim", "RdIdx", "WrIdx", "LastEvt", "FrmRate" ); + for( int i = 0; MYSQL_ROW dbrow = mysql_fetch_row( result ); i++ ) + { + int mon_id = atoi(dbrow[0]); + int function = atoi(dbrow[1]); + if ( !user || user->canAccess( mon_id ) ) + { + if ( function > 1 ) + { + Monitor *monitor = Monitor::Load( mon_id, false, Monitor::QUERY ); + if ( monitor ) + { + struct timeval tv = monitor->GetTimestamp(); + printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", + monitor->Id(), + function, + monitor->GetState(), + monitor->GetTriggerState(), + tv.tv_sec, tv.tv_usec/10000, + monitor->GetLastReadIndex(), + monitor->GetLastWriteIndex(), + monitor->GetLastEvent(), + monitor->GetFPS() + ); + delete monitor; + } + } + else + { + struct timeval tv = { 0, 0 }; + printf( "%4d%5d%6d%9d%11ld.%02ld%6d%6d%8d%8.2f\n", + mon_id, + function, + 0, + 0, + tv.tv_sec, tv.tv_usec/10000, + 0, + 0, + 0, + 0.0 + ); + } + } + } + mysql_free_result( result ); + } + } + delete user; + + return( 0 ); +} diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 000000000..9788f7023 --- /dev/null +++ b/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/stamp-h1 b/stamp-h1 new file mode 100644 index 000000000..4547fe1b5 --- /dev/null +++ b/stamp-h1 @@ -0,0 +1 @@ +timestamp for config.h diff --git a/umutils/nextimeconfigure.zm b/umutils/nextimeconfigure.zm new file mode 100755 index 000000000..e2c0e2f32 --- /dev/null +++ b/umutils/nextimeconfigure.zm @@ -0,0 +1,16 @@ +#!/bin/bash + +#http://tom.webarts.ca/Blog/new-blog-items/buildingzoneminderandrequiredffmpegandx264fromsource + +export LD_LIBRARY_PATH="/usr/local/lib:/opt/libjpeg-turbo/lib:$LD_LIBRARY_PATH" +export LDFLAGS=" -L/home/nextime/zm/libjpeg-turbo-1.2.1/.libs " + + +DEB_HOST_GNU_TYPE=$(dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE=$(dpkg-architecture -qDEB_BUILD_GNU_TYPE) + +CXXFLAGS=" -DZM_FFMPEG_CVS -DHAVE_LIBCRYPTO -msse2 -DJPEG_INCLUDE_DIR=/home/nextime/zm/libjpeg-turbo-1.2.1/ " +CXXFLAGS="$CXXFLAGS -I/home/nextime/zm/libjpeg-turbo-1.2.1/ " + +CXXFLAGS="$CXXFLAGS" ./configure --with-libarch=lib/$DEB_HOST_GNU_TYPE --disable-debug --host=$DEB_HOST_GNU_TYPE --build=$DEB_BUILD_GNU_TYPE --sysconfdir=/etc/zm --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-mysql=/usr --with-webdir=/usr/share/zoneminder --with-ffmpeg=/usr --with-cgidir=/usr/lib/cgi-bin --with-webuser=www-data --with-webgroup=www-data --enable-crashtrace=no --enable-mmap=yes + diff --git a/web/Makefile.am b/web/Makefile.am new file mode 100644 index 000000000..077a4ff91 --- /dev/null +++ b/web/Makefile.am @@ -0,0 +1,35 @@ +AUTOMAKE_OPTIONS = gnu + +# This should be set to your web directory +webdir = @WEB_PREFIX@ +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ + +SUBDIRS = \ + ajax \ + css \ + graphics \ + includes \ + js \ + lang \ + skins \ + tools \ + views + +dist_web_DATA = \ + index.php + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(webdir); chown $(webuser):$(webgroup) $(dist_web_DATA) ) + ( cd $(DESTDIR)$(webdir); chown -R $(webuser):$(webgroup) $(SUBDIRS) ) + @-( cd $(DESTDIR)$(webdir); if ! test -e events; then mkdir events; fi; chown $(webuser):$(webgroup) events; chmod u+w events ) + @-( cd $(DESTDIR)$(webdir); if ! test -e images; then mkdir images; fi; chown $(webuser):$(webgroup) images; chmod u+w images ) + @-( cd $(DESTDIR)$(webdir); if ! test -e sounds; then mkdir sounds; fi; chown $(webuser):$(webgroup) sounds; chmod u+w sounds ) + @-( cd $(DESTDIR)$(webdir); if ! test -e tools; then mkdir tools; fi; chown $(webuser):$(webgroup) tools; chmod u+w tools ) + @-( cd $(DESTDIR)$(webdir); if ! test -e temp; then mkdir temp; fi; chown $(webuser):$(webgroup) temp; chmod u+w temp ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -rf $(SUBDIRS) ) + @-( cd $(DESTDIR)$(webdir); rm -rf events images sounds tools temp ) diff --git a/web/Makefile.in b/web/Makefile.in new file mode 100644 index 000000000..8757f668c --- /dev/null +++ b/web/Makefile.in @@ -0,0 +1,685 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu + +# This should be set to your web directory +webdir = @WEB_PREFIX@ +# And these to the user and group of your webserver +webuser = @WEB_USER@ +webgroup = @WEB_GROUP@ +SUBDIRS = \ + ajax \ + css \ + graphics \ + includes \ + js \ + lang \ + skins \ + tools \ + views + +dist_web_DATA = \ + index.php + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-data-am install-strip tags-recursive \ + uninstall-am + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-data-hook \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA uninstall-hook + + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(webdir); chown $(webuser):$(webgroup) $(dist_web_DATA) ) + ( cd $(DESTDIR)$(webdir); chown -R $(webuser):$(webgroup) $(SUBDIRS) ) + @-( cd $(DESTDIR)$(webdir); if ! test -e events; then mkdir events; fi; chown $(webuser):$(webgroup) events; chmod u+w events ) + @-( cd $(DESTDIR)$(webdir); if ! test -e images; then mkdir images; fi; chown $(webuser):$(webgroup) images; chmod u+w images ) + @-( cd $(DESTDIR)$(webdir); if ! test -e sounds; then mkdir sounds; fi; chown $(webuser):$(webgroup) sounds; chmod u+w sounds ) + @-( cd $(DESTDIR)$(webdir); if ! test -e tools; then mkdir tools; fi; chown $(webuser):$(webgroup) tools; chmod u+w tools ) + @-( cd $(DESTDIR)$(webdir); if ! test -e temp; then mkdir temp; fi; chown $(webuser):$(webgroup) temp; chmod u+w temp ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -rf $(SUBDIRS) ) + @-( cd $(DESTDIR)$(webdir); rm -rf events images sounds tools temp ) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/ajax/Makefile.am b/web/ajax/Makefile.am new file mode 100644 index 000000000..ef79e6cae --- /dev/null +++ b/web/ajax/Makefile.am @@ -0,0 +1,12 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/ajax + +dist_web_DATA = \ + alarm.php \ + control.php \ + event.php \ + log.php \ + status.php \ + stream.php \ + zone.php diff --git a/web/ajax/Makefile.in b/web/ajax/Makefile.in new file mode 100644 index 000000000..27c21d99f --- /dev/null +++ b/web/ajax/Makefile.in @@ -0,0 +1,459 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/ajax +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/ajax +dist_web_DATA = \ + alarm.php \ + control.php \ + event.php \ + log.php \ + status.php \ + stream.php \ + zone.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/ajax/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/ajax/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/ajax/alarm.php b/web/ajax/alarm.php new file mode 100644 index 000000000..b1f5f1496 --- /dev/null +++ b/web/ajax/alarm.php @@ -0,0 +1,42 @@ + diff --git a/web/ajax/control.php b/web/ajax/control.php new file mode 100644 index 000000000..227082f63 --- /dev/null +++ b/web/ajax/control.php @@ -0,0 +1,64 @@ +'.join( ' // ', $ctrlOutput ) ); + ajaxResponse( 'Used script' ); + } + } + else + { + ajaxError( "No command received" ); + } +} + +ajaxError( 'Unrecognised action or insufficient permissions' ); + +function ajaxCleanup() +{ + global $socket; + if ( !empty( $socket ) ) + @socket_close( $socket ); +} +?> diff --git a/web/ajax/event.php b/web/ajax/event.php new file mode 100644 index 000000000..bb8341727 --- /dev/null +++ b/web/ajax/event.php @@ -0,0 +1,124 @@ +$videoFile ) ); + else + ajaxError( "Video Generation Failed" ); + } + $ok = true; + break; + } + case 'deleteVideo' : + { + unlink( $videoFiles[$_REQUEST['id']] ); + unset( $videoFiles[$_REQUEST['id']] ); + ajaxResponse(); + break; + } + case "export" : + { + require_once( ZM_SKIN_PATH.'/includes/export_functions.php' ); + + if ( !empty($_REQUEST['exportDetail']) ) + $exportDetail = $_SESSION['export']['detail'] = $_REQUEST['exportDetail']; + else + $exportDetail = false; + if ( !empty($_REQUEST['exportFrames']) ) + $exportFrames = $_SESSION['export']['frames'] = $_REQUEST['exportFrames']; + else + $exportFrames = false; + if ( !empty($_REQUEST['exportImages']) ) + $exportImages = $_SESSION['export']['images'] = $_REQUEST['exportImages']; + else + $exportImages = false; + if ( !empty($_REQUEST['exportVideo']) ) + $exportVideo = $_SESSION['export']['video'] = $_REQUEST['exportVideo']; + else + $exportVideo = false; + if ( !empty($_REQUEST['exportMisc']) ) + $exportMisc = $_SESSION['export']['misc'] = $_REQUEST['exportMisc']; + else + $exportMisc = false; + if ( !empty($_REQUEST['exportFormat']) ) + $exportFormat = $_SESSION['export']['format'] = $_REQUEST['exportFormat']; + else + $exportFormat = ''; + + $exportIds = !empty($_REQUEST['eids'])?$_REQUEST['eids']:$_REQUEST['id']; + if ( $exportFile = exportEvents( $exportIds, $exportDetail, $exportFrames, $exportImages, $exportVideo, $exportMisc, $exportFormat ) ) + ajaxResponse( array( 'exportFile'=>$exportFile ) ); + else + ajaxError( "Export Failed" ); + break; + } + } +} + +if ( canEdit( 'Events' ) ) +{ + switch ( $_REQUEST['action'] ) + { + case "rename" : + { + if ( !empty($_REQUEST['eventName']) ) + dbQuery( "update Events set Name = '".dbEscape($_REQUEST['eventName'])."' where Id = '".dbEscape($_REQUEST['id'])."'" ); + else + ajaxError( "No new event name supplied" ); + ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); + break; + } + case "eventdetail" : + { + dbQuery( "update Events set Cause = '".dbEscape($_REQUEST['newEvent']['Cause'])."', Notes = '".dbEscape($_REQUEST['newEvent']['Notes'])."' where Id = '".dbEscape($_REQUEST['id'])."'" ); + ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>true ) ); + break; + } + case "archive" : + case "unarchive" : + { + $archiveVal = ($_REQUEST['action'] == "archive")?1:0; + dbQuery( "update Events set Archived = ".$archiveVal." where Id = '".dbEscape($_REQUEST['id'])."'" ); + ajaxResponse( array( 'refreshEvent'=>true, 'refreshParent'=>false ) ); + break; + } + case "delete" : + { + deleteEvent( dbEscape($_REQUEST['id']) ); + ajaxResponse( array( 'refreshEvent'=>false, 'refreshParent'=>true ) ); + break; + } + } +} + +ajaxError( 'Unrecognised action or insufficient permissions' ); + +?> diff --git a/web/ajax/log.php b/web/ajax/log.php new file mode 100644 index 000000000..6dd1e0548 --- /dev/null +++ b/web/ajax/log.php @@ -0,0 +1,363 @@ + "web_js" ) ); + + $string = $_POST['message']; + $file = preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] ); + if ( !empty( $_POST['line'] ) ) + $line = $_POST['line']; + else + $line = NULL; + + $levels = array_flip(Logger::$codes); + if ( !isset($levels[$_POST['level']]) ) + Panic( "Unexpected logger level '".$_POST['level']."'" ); + $level = $levels[$_POST['level']]; + Logger::fetch()->logPrint( $level, $string, $file, $line ); + } + ajaxResponse(); + break; + } + case 'query' : + { + if ( !canView( 'System' ) ) + ajaxError( 'Insufficient permissions to view log entries' ); + + $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; + $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; + $limit = isset($_POST['limit'])?$_POST['limit']:1000; + $filter = isset($_POST['filter'])?$_POST['filter']:array(); + $sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; + $sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'desc'; + + $filterFields = array( 'Component', 'Pid', 'Level', 'File', 'Line' ); + + //$filterSql = $filter?' where + $countSql = "select count(*) as Total from Logs"; + $total = dbFetchOne( $countSql, 'Total' ); + $sql = "select * from Logs"; + $where = array(); + if ( $minTime ) + $where[] = "TimeKey > ".dbEscape($minTime); + elseif ( $maxTime ) + $where[] = "TimeKey < ".dbEscape($maxTime); + foreach ( $filter as $field=>$value ) + if ( $field == 'Level' ) + $where[] = dbEscape($field)." <= ".dbEscape($value); + else + $where[] = dbEscape($field)." = '".dbEscape($value)."'"; + if ( count($where) ) + $sql.= " where ".join( " and ", $where ); + $sql .= " order by ".dbEscape($sortField)." ".dbEscape($sortOrder)." limit ".dbEscape($limit); + $logs = array(); + foreach ( dbFetchAll( $sql ) as $log ) + { + $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); + $logs[] = $log; + } + $options = array(); + $where = array(); + foreach( $filter as $field=>$value ) + if ( $field == 'Level' ) + $where[$field] = dbEscape($field)." <= ".dbEscape($value); + else + $where[$field] = dbEscape($field)." = '".dbEscape($value)."'"; + foreach( $filterFields as $field ) + { + $sql = "select distinct $field from Logs where not isnull($field)"; + $fieldWhere = array_diff_key( $where, array( $field=>true ) ); + if ( count($fieldWhere) ) + $sql.= " and ".join( " and ", $fieldWhere ); + $sql.= " order by $field asc"; + if ( $field == 'Level' ) + { + foreach( dbFetchAll( $sql, $field ) as $value ) + if ( $value <= Logger::INFO ) + $options[$field][$value] = Logger::$codes[$value]; + else + $options[$field][$value] = "DB".$value; + } + else + { + foreach( dbFetchAll( $sql, $field ) as $value ) + if ( $value != '' ) + $options[$field][] = $value; + } + } + if ( count($filter) ) + { + $sql = "select count(*) as Available from Logs where ".join( " and ", $where ); + $available = dbFetchOne( $sql, 'Available' ); + } + ajaxResponse( array( + 'updated' => preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG ), + 'total' => $total, + 'available' => isset($available)?$available:$total, + 'logs' => $logs, + 'state' => logState(), + 'options' => $options + ) ); + break; + } + case 'export' : + { + if ( !canView( 'System' ) ) + ajaxError( 'Insufficient permissions to export logs' ); + + $minTime = isset($_POST['minTime'])?$_POST['minTime']:NULL; + $maxTime = isset($_POST['maxTime'])?$_POST['maxTime']:NULL; + if ( !is_null($minTime) && !is_null($maxTime) && $minTime > $maxTime ) + { + $tempTime = $minTime; + $minTime = $maxTime; + $maxTime = $tempTime; + } + //$limit = isset($_POST['limit'])?$_POST['limit']:1000; + $filter = isset($_POST['filter'])?$_POST['filter']:array(); + $sortField = isset($_POST['sortField'])?$_POST['sortField']:'TimeKey'; + $sortOrder = isset($_POST['sortOrder'])?$_POST['sortOrder']:'asc'; + + $sql = "select * from Logs"; + $where = array(); + if ( $minTime ) + { + preg_match( '/(.+)(\.\d+)/', $minTime, $matches ); + $minTime = strtotime($matches[1]).$matches[2]; + $where[] = "TimeKey >= ".$minTime; + } + if ( $maxTime ) + { + preg_match( '/(.+)(\.\d+)/', $maxTime, $matches ); + $maxTime = strtotime($matches[1]).$matches[2]; + $where[] = "TimeKey <= ".$maxTime; + } + foreach ( $filter as $field=>$value ) + if ( $value != '' ) + if ( $field == 'Level' ) + $where[] = dbEscape($field)." <= ".dbEscape($value); + else + $where[] = dbEscape($field)." = '".dbEscape($value)."'"; + if ( count($where) ) + $sql.= " where ".join( " and ", $where ); + $sql .= " order by ".dbEscape($sortField)." ".dbEscape($sortOrder); + //$sql .= " limit ".dbEscape($limit); + $format = isset($_POST['format'])?$_POST['format']:'text'; + switch( $format ) + { + case 'text' : + $exportExt = "txt"; + break; + case 'tsv' : + $exportExt = "tsv"; + break; + case 'html' : + $exportExt = "html"; + break; + case 'xml' : + $exportExt = "xml"; + break; + default : + Fatal( "Unrecognised log export format '$format'" ); + } + $exportKey = substr(md5(rand()),0,8); + $exportFile = "zm-log.$exportExt"; + $exportPath = "temp/zm-log-$exportKey.$exportExt"; + if ( !($exportFP = fopen( $exportPath, "w" )) ) + Fatal( "Unable to open log export file $exportFile" ); + $logs = array(); + foreach ( dbFetchAll( $sql ) as $log ) + { + $log['DateTime'] = preg_replace( '/^\d+/', strftime( "%Y-%m-%d %H:%M:%S", intval($log['TimeKey']) ), $log['TimeKey'] ); + $logs[] = $log; + } + switch( $format ) + { + case 'text' : + { + foreach ( $logs as $log ) + { + if ( $log['Line'] ) + fprintf( $exportFP, "%s %s[%d].%s-%s/%d [%s]\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Line'], $log['Message'] ); + else + fprintf( $exportFP, "%s %s[%d].%s-%s [%s]\n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['File'], $log['Message'] ); + } + break; + } + case 'tsv' : + { + fprintf( $exportFP, $SLANG['DateTime']."\t".$SLANG['Component']."\t".$SLANG['Pid']."\t".$SLANG['Level']."\t".$SLANG['Message']."\t".$SLANG['File']."\t".$SLANG['Line']."\n" ); + 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'] ); + } + break; + } + case 'html' : + { + fwrite( $exportFP, +' + + + '.$SLANG['ZoneMinderLog'].' + + + +

'.$SLANG['ZoneMinderLog'].'

+

'.htmlspecialchars(preg_match( '/%/', DATE_FMT_CONSOLE_LONG )?strftime( DATE_FMT_CONSOLE_LONG ):date( DATE_FMT_CONSOLE_LONG )).'

+

'.count($logs).' '.$SLANG['Logs'].'

+ + + +' ); + foreach ( $logs as $log ) + { + $classLevel = $log['Level']; + if ( $classLevel < Logger::FATAL ) + $classLevel = Logger::FATAL; + elseif ( $classLevel > Logger::DEBUG ) + $classLevel = Logger::DEBUG; + $logClass = 'log-'.strtolower(Logger::$codes[$classLevel]); + fprintf( $exportFP, " \n", $logClass, $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], $log['Message'], $log['File'], $log['Line'] ); + } + fwrite( $exportFP, +' +
'.$SLANG['DateTime'].''.$SLANG['Component'].''.$SLANG['Pid'].''.$SLANG['Level'].''.$SLANG['Message'].''.$SLANG['File'].''.$SLANG['Line'].'
%s%s%d%s%s%s%s
+ +' ); + break; + } + case 'xml' : + { + fwrite( $exportFP, +' + + '.$_POST['selector'].'' ); + foreach ( $filter as $field=>$value ) + if ( $value != '' ) + fwrite( $exportFP, +' + <'.strtolower($field).'>'.htmlspecialchars($value).' + ' ); + fwrite( $exportFP, +' + '.$SLANG['DateTime'].''.$SLANG['Component'].''.$SLANG['Pid'].''.$SLANG['Level'].''.$SLANG['Message'].''.$SLANG['File'].''.$SLANG['Line'].' + + +' ); + foreach ( $logs as $log ) + { + fprintf( $exportFP, +" + %s + %s + %d + %s + + %s + %d + \n", $log['DateTime'], $log['Component'], $log['Pid'], $log['Code'], utf8_decode( $log['Message'] ), $log['File'], $log['Line'] ); + } + fwrite( $exportFP, +' +' ); + break; + } + $exportExt = "xml"; + break; + } + fclose( $exportFP ); + ajaxResponse( array( + 'key' => $exportKey, + 'format' => $format, + ) ); + break; + } + case 'download' : + { + if ( !canView( 'System' ) ) + ajaxError( 'Insufficient permissions to download logs' ); + + if ( empty($_REQUEST['key']) ) + Fatal( "No log export key given" ); + $exportKey = $_REQUEST['key']; + if ( empty($_REQUEST['format']) ) + Fatal( "No log export format given" ); + $format = $_REQUEST['format']; + + switch( $format ) + { + case 'text' : + $exportExt = "txt"; + break; + case 'tsv' : + $exportExt = "tsv"; + break; + case 'html' : + $exportExt = "html"; + break; + case 'xml' : + $exportExt = "xml"; + break; + default : + Fatal( "Unrecognised log export format '$format'" ); + } + + $exportFile = "zm-log.$exportExt"; + $exportPath = "temp/zm-log-$exportKey.$exportExt"; + + header( "Pragma: public" ); + header( "Expires: 0" ); + header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" ); + header( "Cache-Control: private", false ); // required by certain browsers + header( "Content-Description: File Transfer" ); + header( 'Content-Disposition: attachment; filename="'.$exportFile.'"' ); + header( "Content-Transfer-Encoding: binary" ); + header( "Content-Type: application/force-download" ); + header( "Content-Length: ".filesize($exportPath) ); + readfile( $exportPath ); + exit( 0 ); + break; + } +} + +ajaxError( 'Unrecognised action or insufficient permissions' ); + +?> diff --git a/web/ajax/status.php b/web/ajax/status.php new file mode 100644 index 000000000..fe82fe5cc --- /dev/null +++ b/web/ajax/status.php @@ -0,0 +1,413 @@ + array( + "permission" => "System", + "table" => "Monitors", + "limit" => 1, + "elements" => array( + "MonitorCount" => array( "sql" => "count(*)" ), + "ActiveMonitorCount" => array( "sql" => "count(if(Function != 'None',1,NULL))" ), + "State" => array( "func" => "daemonCheck()?".$SLANG['Running'].":".$SLANG['Stopped'] ), + "Load" => array( "func" => "getLoad()" ), + "Disk" => array( "func" => "getDiskPercent()" ), + ), + ), + "monitor" => array( + "permission" => "Monitors", + "table" => "Monitors", + "limit" => 1, + "selector" => "Monitors.Id", + "elements" => array( + "Id" => array( "sql" => "Monitors.Id" ), + "Name" => array( "sql" => "Monitors.Name" ), + "Type" => true, + "Function" => true, + "Enabled" => true, + "LinkedMonitors" => true, + "Triggers" => true, + "Device" => true, + "Channel" => true, + "Format" => true, + "Host" => true, + "Port" => true, + "Path" => true, + "Width" => array( "sql" => "Monitors.Width" ), + "Height" => array( "sql" => "Monitors.Height" ), + "Palette" => true, + "Orientation" => true, + "Brightness" => true, + "Contrast" => true, + "Hue" => true, + "Colour" => true, + "EventPrefix" => true, + "LabelFormat" => true, + "LabelX" => true, + "LabelY" => true, + "ImageBufferCount" => true, + "WarmupCount" => true, + "PreEventCount" => true, + "PostEventCount" => true, + "AlarmFrameCount" => true, + "SectionLength" => true, + "FrameSkip" => true, + "MaxFPS" => true, + "AlarmMaxFPS" => true, + "FPSReportInterval" => true, + "RefBlendPerc" => true, + "Controllable" => true, + "ControlId" => true, + "ControlDevice" => true, + "ControlAddress" => true, + "AutoStopTimeout" => true, + "TrackMotion" => true, + "TrackDelay" => true, + "ReturnLocation" => true, + "ReturnDelay" => true, + "DefaultView" => true, + "DefaultRate" => true, + "DefaultScale" => true, + "WebColour" => true, + "Sequence" => true, + "MinEventId" => array( "sql" => "min(Events.Id)", "table" => "Events", "join" => "Events.MonitorId = Monitors.Id", "group" => "Events.MonitorId" ), + "MaxEventId" => array( "sql" => "max(Events.Id)", "table" => "Events", "join" => "Events.MonitorId = Monitors.Id", "group" => "Events.MonitorId" ), + "TotalEvents" => array( "sql" => "count(Events.Id)", "table" => "Events", "join" => "Events.MonitorId = Monitors.Id", "group" => "Events.MonitorId" ), + "Status" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -s" ), + "FrameRate" => array( "zmu" => "-m ".escapeshellarg($_REQUEST['id'][0])." -f" ), + ), + ), + "events" => array( + "permission" => "Events", + "table" => "Events", + "selector" => "Events.MonitorId", + "elements" => array( + "Id" => true, + "Name" => true, + "Cause" => true, + "Notes" => true, + "StartTime" => true, + "StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), + "EndTime" => true, + "Width" => true, + "Height" => true, + "Length" => true, + "Frames" => true, + "AlarmFrames" => true, + "TotScore" => true, + "AvgScore" => true, + "MaxScore" => true, + ), + ), + "event" => array( + "permission" => "Events", + "table" => "Events", + "limit" => 1, + "selector" => "Events.Id", + "elements" => array( + "Id" => array( "sql" => "Events.Id" ), + "MonitorId" => true, + "Name" => true, + "Cause" => true, + "StartTime" => true, + "StartTimeShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), + "EndTime" => true, + "Width" => true, + "Height" => true, + "Length" => true, + "Frames" => true, + "AlarmFrames" => true, + "TotScore" => true, + "AvgScore" => true, + "MaxScore" => true, + "Archived" => true, + "Videoed" => true, + "Uploaded" => true, + "Emailed" => true, + "Messaged" => true, + "Executed" => true, + "Notes" => true, + "MinFrameId" => array( "sql" => "min(Frames.FrameId)", "table" => "Frames", "join" => "Events.Id = Frames.EventId", "group" => "Frames.EventId" ), + "MaxFrameId" => array( "sql" => "max(Frames.FrameId)", "table" => "Frames", "join" => "Events.Id = Frames.EventId", "group" => "Frames.EventId" ), + "MinFrameDelta" => array( "sql" => "min(Frames.Delta)", "table" => "Frames", "join" => "Events.Id = Frames.EventId", "group" => "Frames.EventId" ), + "MaxFrameDelta" => array( "sql" => "max(Frames.Delta)", "table" => "Frames", "join" => "Events.Id = Frames.EventId", "group" => "Frames.EventId" ), + //"Path" => array( "postFunc" => "getEventPath" ), + ), + ), + "frame" => array( + "permission" => "Events", + "table" => "Frames", + "limit" => 1, + "selector" => array( array( "table" => "Events", "join" => "Events.Id = Frames.EventId", "selector"=>"Events.Id" ), "Frames.FrameId" ), + "elements" => array( + //"Id" => array( "sql" => "Frames.FrameId" ), + "FrameId" => true, + "EventId" => true, + "Type" => true, + "TimeStamp" => true, + "TimeStampShort" => array( "sql" => "date_format( StartTime, '".MYSQL_FMT_DATETIME_SHORT."' )" ), + "Delta" => true, + "Score" => true, + //"Image" => array( "postFunc" => "getFrameImage" ), + ), + ), + "frameimage" => array( + "permission" => "Events", + "func" => "getFrameImage()" + ), + "nearframe" => array( + "permission" => "Events", + "func" => "getNearFrame()" + ), + "nearevents" => array( + "permission" => "Events", + "func" => "getNearEvents()" + ) +); + +function collectData() +{ + global $statusData; + + $entitySpec = &$statusData[strtolower(validJsStr($_REQUEST['entity']))]; + #print_r( $entitySpec ); + if ( !canView( $entitySpec['permission'] ) ) + ajaxError( 'Unrecognised action or insufficient permissions' ); + + if ( !empty($entitySpec['func']) ) + { + $data = eval( "return( ".$entitySpec['func']." );" ); + } + else + { + $data = array(); + $postFuncs = array(); + + $fieldSql = array(); + $joinSql = array(); + $groupSql = array(); + + $elements = &$entitySpec['elements']; + $lc_elements = array_change_key_case( $elements ); + + $id = false; + if ( isset($_REQUEST['id']) ) + if ( !is_array($_REQUEST['id']) ) + $id = array( validJsStr($_REQUEST['id']) ); + else + $id = array_values( $_REQUEST['id'] ); + + if ( !isset($_REQUEST['element']) ) + $_REQUEST['element'] = array_keys( $elements ); + else if ( !is_array($_REQUEST['element']) ) + $_REQUEST['element'] = array( validJsStr($_REQUEST['element']) ); + + if ( isset($entitySpec['selector']) ) + { + if ( !is_array($entitySpec['selector']) ) + $entitySpec['selector'] = array( $entitySpec['selector'] ); + foreach( $entitySpec['selector'] as $selector ) + if ( is_array( $selector ) && isset($selector['table']) && isset($selector['join']) ) + $joinSql[] = "left join ".$selector['table']." on ".$selector['join']; + } + + foreach ( $_REQUEST['element'] as $element ) + { + if ( !($elementData = $lc_elements[strtolower($element)]) ) + ajaxError( "Bad ".validJsStr($_REQUEST['entity'])." element ".$element ); + if ( isset($elementData['func']) ) + $data[$element] = eval( "return( ".$elementData['func']." );" ); + else if ( isset($elementData['postFunc']) ) + $postFuncs[$element] = $elementData['postFunc']; + else if ( isset($elementData['zmu']) ) + $data[$element] = exec( escapeshellcmd( getZmuCommand( " ".$elementData['zmu'] ) ) ); + else + { + if ( isset($elementData['sql']) ) + $fieldSql[] = $elementData['sql']." as ".$element; + else + $fieldSql[] = $element; + if ( isset($elementData['table']) && isset($elementData['join']) ) + { + $joinSql[] = "left join ".$elementData['table']." on ".$elementData['join']; + } + if ( isset($elementData['group']) ) + { + $groupSql[] = $elementData['group']; + } + } + } + + if ( count($fieldSql) ) + { + $sql = "select ".join( ", ", $fieldSql )." from ".$entitySpec['table']; + if ( $joinSql ) + $sql .= " ".join( " ", array_unique( $joinSql ) ); + if ( $id && !empty($entitySpec['selector']) ) + { + $index = 0; + $where = array(); + foreach( $entitySpec['selector'] as $selector ) + { + if ( is_array( $selector ) ) + $where[] = $selector['selector']." = ".dbEscape($id[$index]); + else + $where[] = $selector." = ".dbEscape($id[$index]); + $index++; + } + $sql .= " where ".join( " and ", $where ); + } + if ( $groupSql ) + $sql .= " group by ".join( ",", array_unique( $groupSql ) ); + if ( !empty($_REQUEST['sort']) ) + $sql .= " order by ".dbEscape($_REQUEST['sort']); + if ( !empty($entitySpec['limit']) ) + $limit = $entitySpec['limit']; + elseif ( !empty($_REQUEST['count']) ) + $limit = dbEscape($_REQUEST['count']); + if ( !empty( $limit ) ) + $sql .= " limit ".$limit; + if ( isset($limit) && $limit == 1 ) + { + if ( $sqlData = dbFetchOne( $sql ) ) + { + foreach ( $postFuncs as $element=>$func ) + $sqlData[$element] = eval( 'return( '.$func.'( $sqlData ) );' ); + $data = array_merge( $data, $sqlData ); + } + } + else + { + $count = 0; + foreach( dbFetchAll( $sql ) as $sqlData ) + { + foreach ( $postFuncs as $element=>$func ) + $sqlData[$element] = eval( 'return( '.$func.'( $sqlData ) );' ); + $data[] = $sqlData; + if ( isset($limi) && ++$count >= $limit ) + break; + } + } + } + } + #print_r( $data ); + return( $data ); +} + +$data = collectData(); + +if ( !isset($_REQUEST['layout']) ) +{ + $_REQUEST['layout'] = "json"; +} +switch( $_REQUEST['layout'] ) +{ + case 'xml NOT CURRENTLY SUPPORTED' : + { + header("Content-type: application/xml" ); + echo( ''."\n" ); + echo "<".strtolower($_REQUEST['entity']).">\n"; + foreach ( $data as $key=>$value ) + { + $key = strtolower( $key ); + echo "<$key>".htmlentities($value)."\n"; + } + echo "\n"; + break; + } + case 'json' : + { + $response = array( strtolower(validJsStr($_REQUEST['entity'])) => $data ); + if ( isset($_REQUEST['loopback']) ) + $response['loopback'] = validJsStr($_REQUEST['loopback']); + ajaxResponse( $response ); + break; + } + case 'text' : + { + header("Content-type: text/plain" ); + echo join( " ", array_values( $data ) ); + break; + } +} + +function getFrameImage() +{ + $eventId = dbEscape($_REQUEST['id'][0]); + $frameId = dbEscape($_REQUEST['id'][1]); + + $sql = "select * from Frames where EventId = '".$eventId."' and FrameId = '".$frameId."'"; + if ( !($frame = dbFetchOne( $sql )) ) + { + $frame = array(); + $frame['EventId'] = $eventId; + $frame['FrameId'] = $frameId; + $frame['Type'] = "Virtual"; + } + $event = dbFetchOne( "select * from Events where Id = '".$frame['EventId']."'" ); + $frame['Image'] = getImageSrc( $event, $frame, SCALE_BASE ); + return( $frame ); +} + +function getNearFrame() +{ + $eventId = dbEscape($_REQUEST['id'][0]); + $frameId = dbEscape($_REQUEST['id'][1]); + + $sql = "select FrameId from Frames where EventId = '".$eventId."' and FrameId <= '".$frameId."' order by FrameId desc limit 1"; + if ( !$nearFrameId = dbFetchOne( $sql, 'FrameId' ) ) + { + $sql = "select * from Frames where EventId = '".$eventId."' and FrameId > '".$frameId."' order by FrameId asc limit 1"; + if ( !$nearFrameId = dbFetchOne( $sql, 'FrameId' ) ) + { + return( array() ); + } + } + $_REQUEST['entity'] = "frame"; + $_REQUEST['id'][1] = $nearFrameId; + return( collectData() ); +} + +function getNearEvents() +{ + global $user, $sortColumn, $sortOrder; + + $eventId = dbEscape($_REQUEST['id']); + $event = dbFetchOne( "select * from Events where Id = '".$eventId."'" ); + + parseFilter( $_REQUEST['filter'] ); + parseSort(); + + if ( $user['MonitorIds'] ) + $midSql = " and MonitorId in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; + else + $midSql = ''; + + $sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where ".dbEscape($sortColumn)." ".($sortOrder=='asc'?'<=':'>=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc'); + $result = dbQuery( $sql ); + while ( $id = dbFetchNext( $result, 'Id' ) ) + { + if ( $id == $eventId ) + { + $prevId = dbFetchNext( $result, 'Id' ); + break; + } + } + + $sql = "select E.Id as Id from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder"; + $result = dbQuery( $sql ); + while ( $id = dbFetchNext( $result, 'Id' ) ) + { + if ( $id == $eventId ) + { + $nextId = dbFetchNext( $result, 'Id' ); + break; + } + } + + $result = array( 'EventId'=>$eventId ); + $result['PrevEventId'] = empty($prevId)?0:$prevId; + $result['NextEventId'] = empty($nextId)?0:$nextId; + return( $result ); +} + +?> diff --git a/web/ajax/stream.php b/web/ajax/stream.php new file mode 100644 index 000000000..98cd7c8b9 --- /dev/null +++ b/web/ajax/stream.php @@ -0,0 +1,135 @@ + 0 ) +{ + if ( count($rSockets) != 1 ) + ajaxError( "Bogus return from select, ".count($rSockets)." sockets available" ); +} + +switch( $nbytes = @socket_recvfrom( $socket, $msg, MSG_DATA_SIZE, 0, $remSockFile ) ) +{ + case -1 : + { + ajaxError( "socket_recvfrom( $remSockFile ) failed: ".socket_strerror(socket_last_error()) ); + break; + } + case 0 : + { + ajaxError( "No data to read from socket" ); + break; + } + default : + { + if ( $nbytes != MSG_DATA_SIZE ) + ajaxError( "Got unexpected message size, got $nbytes, expected ".MSG_DATA_SIZE ); + break; + } +} + +$data = unpack( "ltype", $msg ); +switch ( $data['type'] ) +{ + case MSG_DATA_WATCH : + { + $data = unpack( "ltype/imonitor/istate/dfps/ilevel/irate/ddelay/izoom/Cdelayed/Cpaused/Cenabled/Cforced", $msg ); + $data['fps'] = sprintf( "%.2f", $data['fps'] ); + $data['rate'] /= RATE_BASE; + $data['delay'] = sprintf( "%.2f", $data['delay'] ); + $data['zoom'] = sprintf( "%.1f", $data['zoom']/SCALE_BASE ); + ajaxResponse( array( 'status'=>$data ) ); + break; + } + case MSG_DATA_EVENT : + { + $data = unpack( "ltype/ievent/iprogress/irate/izoom/Cpaused", $msg ); + //$data['progress'] = sprintf( "%.2f", $data['progress'] ); + $data['rate'] /= RATE_BASE; + $data['zoom'] = sprintf( "%.1f", $data['zoom']/SCALE_BASE ); + ajaxResponse( array( 'status'=>$data ) ); + break; + } + default : + { + ajaxError( "Unexpected received message type '$type'" ); + } +} + +ajaxError( 'Unrecognised action or insufficient permissions' ); + +function ajaxCleanup() +{ + global $socket, $locSockFile; + if ( !empty( $socket ) ) + @socket_close( $socket ); + if ( !empty( $locSockFile ) ) + @unlink( $locSockFile ); +} +?> diff --git a/web/ajax/zone.php b/web/ajax/zone.php new file mode 100644 index 000000000..1c087541d --- /dev/null +++ b/web/ajax/zone.php @@ -0,0 +1,45 @@ + ZM_DIR_IMAGES.'/Zones'.$monitor['Id'].'.jpg?'.time(), + 'selfIntersecting' => isSelfIntersecting( $points ), + 'area' => getPolyArea( $points ) + ) ); + + break; + } + } +} + +ajaxError( 'Unrecognised action or insufficient permissions' ); + +?> diff --git a/web/css/Makefile.am b/web/css/Makefile.am new file mode 100644 index 000000000..917b8f389 --- /dev/null +++ b/web/css/Makefile.am @@ -0,0 +1,8 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/css + +dist_web_DATA = \ + reset.css \ + spinner.css \ + overlay.css diff --git a/web/css/Makefile.in b/web/css/Makefile.in new file mode 100644 index 000000000..c2494c9d4 --- /dev/null +++ b/web/css/Makefile.in @@ -0,0 +1,455 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/css +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/css +dist_web_DATA = \ + reset.css \ + spinner.css \ + overlay.css + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/css/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/css/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/css/overlay.css b/web/css/overlay.css new file mode 100644 index 000000000..de7ed5ecb --- /dev/null +++ b/web/css/overlay.css @@ -0,0 +1,49 @@ +.overlayMask { + position: absolute; + opacity: 0.6; + filter: alpha(opacity=60); + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=60); + z-index: 999; + background: #aaaaaa; +} + +.overlay { + display: none; + position: absolute; + background-color: #f0f0f0; + border: 2px solid #555555; + -moz-border-radius: 4px; + z-index: 1000; + overflow: hidden; +} + +.overlayHeader { + float: left; + background-color: #dddddd; + width: 100%; + border-bottom: 1px solid #666666; + color: black; +} + +.overlayTitle { + float: left; + padding: 10px 6px; + font-weight: bold; + width: auto; +} + +.overlayToolbar { + float: right; + font-weight: bold; + padding: 6px 4px; + width: auto; +} + +.overlayBody { + float: left; + width: 100%; +} + +.overlayContent { + padding: 4px 4px 6px; +} diff --git a/web/css/reset.css b/web/css/reset.css new file mode 100644 index 000000000..12656ad4c --- /dev/null +++ b/web/css/reset.css @@ -0,0 +1,77 @@ +/* + * ZoneMinder Reset Stylesheet, $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. + */ + +/* + * Based on Reset Reloaded by Eric Meyer at http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ + */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +input, textarea, select, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; +} + +/* remember to define focus styles! */ +:focus { + outline: 0; +} + +body { + line-height: 1; + color: black; + background: white; +} + +ol, ul { + list-style: none; +} + +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: separate; + border-spacing: 0; +} + +caption, th, td { + text-align: left; + font-weight: normal; +} + +blockquote:before, blockquote:after, +q:before, q:after { + content: ""; +} + +blockquote, q { + quotes: "" ""; +} diff --git a/web/css/spinner.css b/web/css/spinner.css new file mode 100644 index 000000000..835d4e665 --- /dev/null +++ b/web/css/spinner.css @@ -0,0 +1,19 @@ +.spinner { + position: absolute; + opacity: 0.9; + filter: alpha(opacity=90); + -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=90); + z-index: 1001; + background: #fff; +} +.spinner-msg { + text-align: center; + font-weight: bold; +} + +.spinner-img { + background: url(/graphics/spinner.gif) no-repeat; + width: 24px; + height: 24px; + margin: 0 auto; +} diff --git a/web/graphics/Makefile.am b/web/graphics/Makefile.am new file mode 100644 index 000000000..ec252c82e --- /dev/null +++ b/web/graphics/Makefile.am @@ -0,0 +1,8 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/graphics + +dist_web_DATA = \ + favicon.ico \ + spinner.gif \ + transparent.gif diff --git a/web/graphics/Makefile.in b/web/graphics/Makefile.in new file mode 100644 index 000000000..4e6e9f5ee --- /dev/null +++ b/web/graphics/Makefile.in @@ -0,0 +1,455 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/graphics +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/graphics +dist_web_DATA = \ + favicon.ico \ + spinner.gif \ + transparent.gif + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/graphics/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/graphics/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/graphics/favicon.ico b/web/graphics/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a42fd483cfd60e62ca54bc118a5456ae9480d8e GIT binary patch literal 318 zcmbu3K?=nn5JMyM0Is_3vIh~okl@y%c{BTBOIym{{TY+YBq&OOjxox$2WhneI~xdE zV5v|3MNQ(UwNqe5_1;kjV;+s+3DCBn^r?Ckc22cA&8cLV#d?_q!y$Ak#@s8Ki^oT~ N`g+&dUH-*CH~?~bUf}=$ literal 0 HcmV?d00001 diff --git a/web/graphics/spinner.gif b/web/graphics/spinner.gif new file mode 100644 index 0000000000000000000000000000000000000000..53dd589fa194f5db985e4301c7a73ed4f1b9ad99 GIT binary patch literal 2545 zcma*pX;2hr8VB%~zPqQp=@B)`y1PS96NXtx1_oS2g;AJ+5se@Q;|&UOs2qwM!p4Ca zhJiUal?ExBdstaT~?f3m?cZgNh{frmzMrfcJ8)3 z;P)BJevgQNtw(cfF&90SnBnnr_M&xm@O%6 zzG;!w8(-4o!w_SKEsx_t8i2dHA{$xug+5j_t}~5!rEMsQGpY^uf8#e!ez!6*c<$`# z%2he_t-h<5RT`BLN|GpKWC}6HY^k+5Dom~L=dCyXf!71bXd=Do;)LbM zv+gGZ*&l+=TYuPh^HJ+{Um3v9W8Dqi zZsIDi!j*rKg;1w`oCOc;={#&)!ZF-E-<0u^i2Q3W!xltD%v-T4#;x)CfF(1Ouv)`p z>uUosDu9aCbKX*^H)pSF(Clw+wK}`3LC8Vd5wn~@j##n&8u(Or9|$_$-*q^|8tR^Ze!v`8XRU12fiFxN&Z^HeB_6{>ZFruBWn5U6U_WQI--B zG~o}Ys+mlEb+PC3o7FVVvN+9%m7%O}Y_c3WoYls|wT3|PzzV{wM+0F|$H`%9CT0Y^ za*mZIUl3}$c$+|-?~lU1Lc0B}sn(uvcimZ5#)MR#za@NWsrn^X=yb^$k3_>|w9gkR z>#sW<_Ea0KR$g0dg}fy7K69z6?%wR47d!o@ zGKEctobW(W=VY|Az1{V$NH$hYU5!_r3z~t<1_3#$IhT`+-0m8Lu3WANjbGvNg1vn1 z=E&h$lM^*FtCrg64J+q9{~$Yc&oK@)FJ9|wdu`CBEMKgD->DcQRuxrUW36azX6kqE z(WAIz&9a^4uqfQXZ?4*+k}M^TI=80q9GA}G8+>bb(fyeR`Q-S93>Q-=OX7E#U^f4~jWk3u>uE&r}55)J9D8+*U}{&~xy z+xheT3lqZ$_0RMat&nbp<_ki!f?+E=jik2kBu@#UnX z0AcCVU-1x`*#iFAGPG4?H)8U+YtUJCS?At3FP6 zWjMo76`C~5oga!z%d+xx$x-ljIYP1$9YjNGd0H&jsWL7XsM^)8O;wB>PVnYYXxtSh|$ifidD)RGQ}R zwHJrNIdVjTqdEklY&;>>dZRxDK`F>#B8Ki@pp8f7rwM2mppszvcw{I`Q1%>g09l6Ekr2-S;;<|g2awum zsj!Q?)Pbyi5x+M!F@WFk6jsdhHiry`x0GIzjy;Yj%rtk*Y|Rg9EEqf3wBpTM<@>(0 zk0}s;bd@I0{9$O~|I{qUIC4vLX&EGrCS`%OyAe_n3}9mSiO7}(QE&#Jdx176W`mkS qJBjK|(6Aas*VCO0)PD%QJkkj;=v4CXc=>?~L(zU/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/includes +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in $(srcdir)/config.php.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = config.php +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) $(web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/includes +web_DATA = \ + config.php + +dist_web_DATA = \ + actions.php \ + database.php \ + functions.php \ + control_functions.php \ + lang.php \ + logger.php + +EXTRA_DIST = \ + config.php.in + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/includes/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/includes/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +config.php: $(top_builddir)/config.status $(srcdir)/config.php.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +install-webDATA: $(web_DATA) + @$(NORMAL_INSTALL) + @list='$(web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-webDATA: + @$(NORMAL_UNINSTALL) + @list='$(web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)" "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA install-webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA uninstall-webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip install-webDATA \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA \ + uninstall-webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/includes/actions.php b/web/includes/actions.php new file mode 100644 index 000000000..1892464a7 --- /dev/null +++ b/web/includes/actions.php @@ -0,0 +1,932 @@ +$type ) + { + if ( preg_match( '/^(Can|Has)/', $name ) ) + { + $types[$name] = 'toggle'; + } + } + $changes = getFormChanges( $control, $_REQUEST['newControl'], $types, $columns ); + + if ( count( $changes ) ) + { + if ( !empty($_REQUEST['cid']) ) + { + dbQuery( "update Controls set ".implode( ", ", $changes )." where Id = '".dbEscape($_REQUEST['cid'])."'" ); + } + else + { + dbQuery( "insert into Controls set ".implode( ", ", $changes ) ); + //$_REQUEST['cid'] = dbInsertId(); + } + $refreshParent = true; + } + $view = 'none'; + } + elseif ( $action == "delete" ) + { + if ( isset($_REQUEST['markCids']) ) + { + foreach( $_REQUEST['markCids'] as $markCid ) + { + dbQuery( "delete from Controls where Id = '".dbEscape($markCid)."'" ); + dbQuery( "update Monitors set Controllable = 0, ControlId = 0 where ControlId = '".dbEscape($markCid)."'" ); + $refreshParent = true; + } + } + } + } + + // Monitor edit actions, require a monitor id and edit permissions for that monitor + if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) + { + $mid = validInt($_REQUEST['mid']); + if ( $action == "function" ) + { + $monitor = dbFetchOne( "select * from Monitors where Id = '".$mid."'" ); + + $newFunction = validStr($_REQUEST['newFunction']); + $newEnabled = validStr($_REQUEST['newEnabled']); + $oldFunction = $monitor['Function']; + $oldEnabled = $monitor['Enabled']; + if ( $newFunction != $oldFunction || $newEnabled != $oldEnabled ) + { + dbQuery( "update Monitors set Function = '".dbEscape($newFunction)."', Enabled = '".$newEnabled."' where Id = '".$mid."'" ); + + $monitor['Function'] = $newFunction; + $monitor['Enabled'] = $newEnabled; + //if ( $cookies ) session_write_close(); + if ( daemonCheck() ) + { + $restart = ($oldFunction == 'None') || ($newFunction == 'None') || ($newEnabled != $oldEnabled); + zmaControl( $monitor, "stop" ); + zmcControl( $monitor, $restart?"restart":"" ); + zmaControl( $monitor, "start" ); + } + $refreshParent = true; + } + } + elseif ( $action == "zone" && isset( $_REQUEST['zid'] ) ) + { + $zid = validInt($_REQUEST['zid']); + $monitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" ); + + if ( !empty($zid) ) + { + $zone = dbFetchOne( "select * from Zones where MonitorId = '".dbEscape($mid)."' and Id = '".dbEscape($zid)."'" ); + } + else + { + $zone = array(); + } + + if ( $_REQUEST['newZone']['Units'] == 'Percent' ) + { + $_REQUEST['newZone']['MinAlarmPixels'] = intval(($_REQUEST['newZone']['MinAlarmPixels']*$_REQUEST['newZone']['Area'])/100); + $_REQUEST['newZone']['MaxAlarmPixels'] = intval(($_REQUEST['newZone']['MaxAlarmPixels']*$_REQUEST['newZone']['Area'])/100); + if ( isset($_REQUEST['newZone']['MinFilterPixels']) ) + $_REQUEST['newZone']['MinFilterPixels'] = intval(($_REQUEST['newZone']['MinFilterPixels']*$_REQUEST['newZone']['Area'])/100); + if ( isset($_REQUEST['newZone']['MaxFilterPixels']) ) + $_REQUEST['newZone']['MaxFilterPixels'] = intval(($_REQUEST['newZone']['MaxFilterPixels']*$_REQUEST['newZone']['Area'])/100); + if ( isset($_REQUEST['newZone']['MinBlobPixels']) ) + $_REQUEST['newZone']['MinBlobPixels'] = intval(($_REQUEST['newZone']['MinBlobPixels']*$_REQUEST['newZone']['Area'])/100); + if ( isset($_REQUEST['newZone']['MaxBlobPixels']) ) + $_REQUEST['newZone']['MaxBlobPixels'] = intval(($_REQUEST['newZone']['MaxBlobPixels']*$_REQUEST['newZone']['Area'])/100); + } + + unset( $_REQUEST['newZone']['Points'] ); + $types = array(); + $changes = getFormChanges( $zone, $_REQUEST['newZone'], $types ); + + if ( count( $changes ) ) + { + if ( $zid > 0 ) + { + $sql = "update Zones set ".implode( ", ", $changes )." where MonitorId = '".dbEscape($mid)."' and Id = '".dbEscape($zid)."'"; + } + else + { + $sql = "insert into Zones set MonitorId = '".dbEscape($mid)."', ".implode( ", ", $changes ); + } + dbQuery( $sql ); + //if ( $cookies ) session_write_close(); + if ( daemonCheck() ) + { + zmaControl( $mid, "restart" ); + } + $refreshParent = true; + } + $view = 'none'; + } + elseif ( $action == "plugin" && isset($_REQUEST['pl'])) + { + $plugin=dbEscape($_REQUEST['pl']); + $zid=validInt($_REQUEST['zid']); + $sql="SELECT * FROM PluginsConfig WHERE MonitorId='".dbEscape($mid)."' AND ZoneId='".$zid."' AND pluginName='".$plugin."'"; + $pconfs=dbFetchAll( $sql ); + $changes=0; + foreach( $pconfs as $pconf ) + { + $value=$_REQUEST['pluginOpt'][$pconf['Name']]; + if(array_key_exists($pconf['Name'], $_REQUEST['pluginOpt']) && ($pconf['Value']!=$value)) + { + dbQuery("UPDATE PluginsConfig SET Value='".dbEscape($value)."' WHERE id='".$pconf['Id']."'"); + $changes++; + } + } + if($changes>0) + { + if ( daemonCheck() ) + { + zmaControl( $mid, "restart" ); + } + $refreshParent = true; + } + $view = 'none'; + } + elseif ( $action == "sequence" && isset($_REQUEST['smid']) ) + { + $smid = validInt($_REQUEST['smid']); + $monitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" ); + $smonitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($smid)."'" ); + + dbQuery( "update Monitors set Sequence = '".$smonitor['Sequence']."' where Id = '".$monitor['Id']."'" ); + dbQuery( "update Monitors set Sequence = '".$monitor['Sequence']."' where Id = '".$smonitor['Id']."'" ); + + $refreshParent = true; + fixSequences(); + } + if ( $action == "delete" ) + { + if ( isset($_REQUEST['markZids']) ) + { + $deletedZid = 0; + foreach( $_REQUEST['markZids'] as $markZid ) + { + dbQuery( "delete from Zones where MonitorId = '".dbEscape($mid)."' && Id = '".dbEscape($markZid)."'" ); + $deletedZid = 1; + } + if ( $deletedZid ) + { + //if ( $cookies ) + //session_write_close(); + if ( daemonCheck() ) + zmaControl( $mid, "restart" ); + $refreshParent = true; + } + } + } + } + + // Monitor edit actions, monitor id derived, require edit permissions for that monitor + if ( canEdit( 'Monitors' ) ) + { + if ( $action == "monitor" ) + { + if ( !empty($_REQUEST['mid']) ) + { + $mid = validInt($_REQUEST['mid']); + $monitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" ); + + if ( ZM_OPT_X10 ) + { + $x10Monitor = dbFetchOne( "select * from TriggersX10 where MonitorId = '".dbEscape($mid)."'" ); + if ( !$x10Monitor ) + $x10Monitor = array(); + } + } + else + { + $monitor = array(); + if ( ZM_OPT_X10 ) + { + $x10Monitor = array(); + } + } + + // Define a field type for anything that's not simple text equivalent + $types = array( + 'Triggers' => 'set', + 'Controllable' => 'toggle', + 'TrackMotion' => 'toggle', + 'Enabled' => 'toggle', + 'DoNativeMotDet' => 'toggle' + ); + + $columns = getTableColumns( 'Monitors' ); + $changes = getFormChanges( $monitor, $_REQUEST['newMonitor'], $types, $columns ); + + if ( count( $changes ) ) + { + if ( !empty($_REQUEST['mid']) ) + { + $mid = validInt($_REQUEST['mid']); + $sql = "update Monitors set ".implode( ", ", $changes )." where Id = '".dbEscape($mid)."'"; + dbQuery( $sql ); + if ( isset($changes['Name']) ) + { + exec( escapeshellcmd( "mv ".ZM_DIR_EVENTS."/".$monitor['Name']." ".ZM_DIR_EVENTS."/".$_REQUEST['newMonitor']['Name'] ) ); + } + if ( isset($changes['Width']) || isset($changes['Height']) ) + { + $newW = $_REQUEST['newMonitor']['Width']; + $newH = $_REQUEST['newMonitor']['Height']; + $newA = $newW * $newH; + $oldW = $monitor['Width']; + $oldH = $monitor['Height']; + $oldA = $oldW * $oldH; + + $zones = dbFetchAll( "select * from Zones where MonitorId = '".dbEscape($mid)."'" ); + foreach ( $zones as $zone ) + { + $newZone = $zone; + $points = coordsToPoints( $zone['Coords'] ); + for ( $i = 0; $i < count($points); $i++ ) + { + $points[$i]['x'] = intval(($points[$i]['x']*($newW-1))/($oldW-1)); + $points[$i]['y'] = intval(($points[$i]['y']*($newH-1))/($oldH-1)); + } + $newZone['Coords'] = pointsToCoords( $points ); + $newZone['Area'] = intval(round(($zone['Area']*$newA)/$oldA)); + $newZone['MinAlarmPixels'] = intval(round(($newZone['MinAlarmPixels']*$newA)/$oldA)); + $newZone['MaxAlarmPixels'] = intval(round(($newZone['MaxAlarmPixels']*$newA)/$oldA)); + $newZone['MinFilterPixels'] = intval(round(($newZone['MinFilterPixels']*$newA)/$oldA)); + $newZone['MaxFilterPixels'] = intval(round(($newZone['MaxFilterPixels']*$newA)/$oldA)); + $newZone['MinBlobPixels'] = intval(round(($newZone['MinBlobPixels']*$newA)/$oldA)); + $newZone['MaxBlobPixels'] = intval(round(($newZone['MaxBlobPixels']*$newA)/$oldA)); + + $changes = getFormChanges( $zone, $newZone, $types ); + + if ( count( $changes ) ) + { + dbQuery( "update Zones set ".implode( ", ", $changes )." where MonitorId = '".dbEscape($mid)."' and Id = '".$zone['Id']."'" ); + } + } + } + } + elseif ( !$user['MonitorIds'] ) + { + $maxSeq = dbFetchOne( "select max(Sequence) as MaxSequence from Monitors", "MaxSequence" ); + $changes[] = "Sequence = ".($maxSeq+1); + + dbQuery( "insert into Monitors set ".implode( ", ", $changes ) ); + $mid = dbInsertId(); + $zoneArea = $_REQUEST['newMonitor']['Width'] * $_REQUEST['newMonitor']['Height']; + dbQuery( "insert into Zones set MonitorId = ".dbEscape($mid).", Name = 'All', Type = 'Active', Units = 'Percent', NumCoords = 4, Coords = '".sprintf( "%d,%d %d,%d %d,%d %d,%d", 0, 0, $_REQUEST['newMonitor']['Width']-1, 0, $_REQUEST['newMonitor']['Width']-1, $_REQUEST['newMonitor']['Height']-1, 0, $_REQUEST['newMonitor']['Height']-1 )."', Area = ".$zoneArea.", AlarmRGB = 0xff0000, CheckMethod = 'Blobs', MinPixelThreshold = 25, MinAlarmPixels = ".intval(($zoneArea*3)/100).", MaxAlarmPixels = ".intval(($zoneArea*75)/100).", FilterX = 3, FilterY = 3, MinFilterPixels = ".intval(($zoneArea*3)/100).", MaxFilterPixels = ".intval(($zoneArea*75)/100).", MinBlobPixels = ".intval(($zoneArea*2)/100).", MinBlobs = 1" ); + //$view = 'none'; + mkdir( ZM_DIR_EVENTS.'/'.$mid, 0755 ); + symlink( $mid, ZM_DIR_EVENTS.'/'.$_REQUEST['newMonitor']['Name'] ); + if ( isset($_COOKIE['zmGroup']) ) + { + $sql = "update Groups set MonitorIds = concat(MonitorIds,',".$mid."') where Id = '".dbEscape($_COOKIE['zmGroup'])."'"; + dbQuery( $sql ); + } + } + $restart = true; + } + + if ( ZM_OPT_X10 ) + { + $x10Changes = getFormChanges( $x10Monitor, $_REQUEST['newX10Monitor'] ); + + if ( count( $x10Changes ) ) + { + if ( $x10Monitor && isset($_REQUEST['newX10Monitor']) ) + { + dbQuery( "update TriggersX10 set ".implode( ", ", $x10Changes )." where MonitorId = '".dbEscape($mid)."'" ); + } + elseif ( !$user['MonitorIds'] ) + { + if ( !$x10Monitor ) + { + dbQuery( "insert into TriggersX10 set MonitorId = '".dbEscape($mid)."', ".implode( ", ", $x10Changes ) ); + } + else + { + dbQuery( "delete from TriggersX10 where MonitorId = '".dbEscape($mid)."'" ); + } + } + $restart = true; + } + } + + if ( $restart ) + { + $monitor = dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" ); + fixDevices(); + //if ( $cookies ) + //session_write_close(); + if ( daemonCheck() ) + { + zmaControl( $monitor, "stop" ); + zmcControl( $monitor, "restart" ); + zmaControl( $monitor, "start" ); + } + //daemonControl( 'restart', 'zmwatch.pl' ); + $refreshParent = true; + } + $view = 'none'; + } + if ( $action == "delete" ) + { + if ( isset($_REQUEST['markMids']) && !$user['MonitorIds'] ) + { + foreach( $_REQUEST['markMids'] as $markMid ) + { + if ( canEdit( 'Monitors', $markMid ) ) + { + $sql = "select * from Monitors where Id = '".dbEscape($markMid)."'"; + if ( $monitor = dbFetchOne( $sql ) ) + { + if ( daemonCheck() ) + { + zmaControl( $monitor, "stop" ); + zmcControl( $monitor, "stop" ); + } + + // This is the important stuff + dbQuery( "delete from Monitors where Id = '".dbEscape($markMid)."'" ); + dbQuery( "delete from Zones where MonitorId = '".dbEscape($markMid)."'" ); + if ( ZM_OPT_X10 ) + dbQuery( "delete from TriggersX10 where MonitorId = '".dbEscape($markMid)."'" ); + + fixSequences(); + + // If fast deletes are on, then zmaudit will clean everything else up later + // If fast deletes are off and there are lots of events then this step may + // well time out before completing, in which case zmaudit will still tidy up + if ( !ZM_OPT_FAST_DELETE ) + { + $sql = "select Id from Events where MonitorId = '".dbEscape($markMid)."'"; + $markEids = dbFetchAll( $sql, 'Id' ); + foreach( $markEids as $markEid ) + deleteEvent( $markEid ); + + deletePath( ZM_DIR_EVENTS."/".$monitor['Name'] ); + deletePath( ZM_DIR_EVENTS."/".$monitor['Id'] ); + } + } + } + } + } + } + } + + // Device view actions + if ( canEdit( 'Devices' ) ) + { + if ( $action == "device" ) + { + if ( !empty($_REQUEST['command']) ) + { + setDeviceStatusX10( $_REQUEST['key'], $_REQUEST['command'] ); + } + elseif ( isset( $_REQUEST['newDevice'] ) ) + { + if ( isset($_REQUEST['did']) ) + { + dbQuery( "update Devices set Name = '".dbEscape($_REQUEST['newDevice']['Name'])."', KeyString = '".dbEscape($_REQUEST['newDevice']['KeyString'])."' where Id = '".dbEscape($_REQUEST['did'])."'" ); + } + else + { + dbQuery( "insert into Devices set Name = '".dbEscape($_REQUEST['newDevice']['Name'])."', KeyString = '".dbEscape($_REQUEST['newDevice']['KeyString'])."'" ); + } + $refreshParent = true; + $view = 'none'; + } + } + elseif ( $action == "delete" ) + { + if ( isset($_REQUEST['markDids']) ) + { + foreach( $_REQUEST['markDids'] as $markDid ) + { + dbQuery( "delete from Devices where Id = '".dbEscape($markDid)."'" ); + $refreshParent = true; + } + } + } + } + + // System view actions + if ( canView( 'System' ) ) + { + if ( $action == "setgroup" ) + { + if ( !empty($_REQUEST['gid']) ) + { + setcookie( "zmGroup", validInt($_REQUEST['gid']), time()+3600*24*30*12*10 ); + } + else + { + setcookie( "zmGroup", "", time()-3600*24*2 ); + } + $refreshParent = true; + } + } + + // System edit actions + if ( canEdit( 'System' ) ) + { + if ( $action == "version" && isset($_REQUEST['option']) ) + { + $option = $_REQUEST['option']; + switch( $option ) + { + case 'go' : + { + // Ignore this, the caller will open the page itself + break; + } + case 'ignore' : + { + dbQuery( "update Config set Value = '".ZM_DYN_LAST_VERSION."' where Name = 'ZM_DYN_CURR_VERSION'" ); + break; + } + case 'hour' : + case 'day' : + case 'week' : + { + $nextReminder = time(); + if ( $option == 'hour' ) + { + $nextReminder += 60*60; + } + elseif ( $option == 'day' ) + { + $nextReminder += 24*60*60; + } + elseif ( $option == 'week' ) + { + $nextReminder += 7*24*60*60; + } + dbQuery( "update Config set Value = '".$nextReminder."' where Name = 'ZM_DYN_NEXT_REMINDER'" ); + break; + } + case 'never' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_CHECK_FOR_UPDATES'" ); + break; + } + } + } + if ( $action == "donate" && isset($_REQUEST['option']) ) + { + $option = $_REQUEST['option']; + switch( $option ) + { + case 'go' : + { + // Ignore this, the caller will open the page itself + break; + } + case 'hour' : + case 'day' : + case 'week' : + case 'month' : + { + $nextReminder = time(); + if ( $option == 'hour' ) + { + $nextReminder += 60*60; + } + elseif ( $option == 'day' ) + { + $nextReminder += 24*60*60; + } + elseif ( $option == 'week' ) + { + $nextReminder += 7*24*60*60; + } + elseif ( $option == 'month' ) + { + $nextReminder += 30*24*60*60; + } + dbQuery( "update Config set Value = '".$nextReminder."' where Name = 'ZM_DYN_DONATE_REMINDER_TIME'" ); + break; + } + case 'never' : + case 'already' : + { + dbQuery( "update Config set Value = '0' where Name = 'ZM_DYN_SHOW_DONATE_REMINDER'" ); + break; + } + } + } + if ( $action == "options" && isset($_REQUEST['tab']) ) + { + $configCat = $configCats[$_REQUEST['tab']]; + $changed = false; + foreach ( $configCat as $name=>$value ) + { + unset( $newValue ); + if ( $value['Type'] == "boolean" && empty($_REQUEST['newConfig'][$name]) ) + $newValue = 0; + elseif ( isset($_REQUEST['newConfig'][$name]) ) + $newValue = preg_replace( "/\r\n/", "\n", stripslashes( $_REQUEST['newConfig'][$name] ) ); + + if ( isset($newValue) && ($newValue != $value['Value']) ) + { + dbQuery( "update Config set Value = '".$newValue."' where Name = '".$name."'" ); + $changed = true; + } + } + if ( $changed ) + { + switch( $_REQUEST['tab'] ) + { + case "system" : + case "config" : + case "paths" : + $restartWarning = true; + break; + case "web" : + case "tools" : + break; + case "logging" : + case "network" : + case "mail" : + case "upload" : + $restartWarning = true; + break; + case "highband" : + case "medband" : + case "lowband" : + case "phoneband" : + break; + } + } + loadConfig( false ); + } + elseif ( $action == "user" ) + { + if ( !empty($_REQUEST['uid']) ) + $dbUser = dbFetchOne( "select * from Users where Id = '".dbEscape($_REQUEST['uid'])."'" ); + else + $dbUser = array(); + + $types = array(); + $changes = getFormChanges( $dbUser, $_REQUEST['newUser'], $types ); + + if ( $_REQUEST['newUser']['Password'] ) + $changes['Password'] = "Password = password('".dbEscape($_REQUEST['newUser']['Password'])."')"; + else + unset( $changes['Password'] ); + + if ( count( $changes ) ) + { + if ( !empty($_REQUEST['uid']) ) + { + $sql = "update Users set ".implode( ", ", $changes )." where Id = '".dbEscape($_REQUEST['uid'])."'"; + } + else + { + $sql = "insert into Users set ".implode( ", ", $changes ); + } + dbQuery( $sql ); + $refreshParent = true; + if ( $dbUser['Username'] == $user['Username'] ) + userLogin( $dbUser['Username'], $dbUser['Password'] ); + } + $view = 'none'; + } + elseif ( $action == "state" ) + { + if ( !empty($_REQUEST['runState']) ) + { + //if ( $cookies ) session_write_close(); + packageControl( $_REQUEST['runState'] ); + $refreshParent = true; + } + } + elseif ( $action == "save" ) + { + if ( !empty($_REQUEST['runState']) || !empty($_REQUEST['newState']) ) + { + $sql = "select Id,Function,Enabled from Monitors order by Id"; + $definitions = array(); + foreach( dbFetchAll( $sql ) as $monitor ) + { + $definitions[] = $monitor['Id'].":".$monitor['Function'].":".$monitor['Enabled']; + } + $definition = join( ',', $definitions ); + if ( $_REQUEST['newState'] ) + $_REQUEST['runState'] = $_REQUEST['newState']; + dbQuery( "replace into States set Name = '".dbEscape($_REQUEST['runState'])."', Definition = '".dbEscape($definition)."'" ); + } + } + elseif ( $action == "group" ) + { + if ( !empty($_REQUEST['gid']) ) + { + $sql = "update Groups set Name = '".dbEscape($_REQUEST['newGroup']['Name'])."', MonitorIds = '".dbEscape(join(',',$_REQUEST['newGroup']['MonitorIds']))."' where Id = '".dbEscape($_REQUEST['gid'])."'"; + } + else + { + $sql = "insert into Groups set Name = '".dbEscape($_REQUEST['newGroup']['Name'])."', MonitorIds = '".dbEscape(join(',',$_REQUEST['newGroup']['MonitorIds']))."'"; + } + dbQuery( $sql ); + $refreshParent = true; + $view = 'none'; + } + elseif ( $action == "delete" ) + { + if ( isset($_REQUEST['runState']) ) + dbQuery( "delete from States where Name = '".dbEscape($_REQUEST['runState'])."'" ); + + if ( isset($_REQUEST['markUids']) ) + { + foreach( $_REQUEST['markUids'] as $markUid ) + dbQuery( "delete from Users where Id = '".dbEscape($markUid)."'" ); + if ( $markUid == $user['Id'] ) + userLogout(); + } + if ( !empty($_REQUEST['gid']) ) + { + dbQuery( "delete from Groups where Id = '".dbEscape($_REQUEST['gid'])."'" ); + if ( isset($_COOKIE['zmGroup']) ) + { + if ( $_REQUEST['gid'] == $_COOKIE['zmGroup'] ) + { + unset( $_COOKIE['zmGroup'] ); + setcookie( "zmGroup", "", time()-3600*24*2 ); + $refreshParent = true; + } + } + } + } + } + else + { + if ( ZM_USER_SELF_EDIT && $action == "user" ) + { + $uid = $user['Id']; + + $dbUser = dbFetchOne( "select Id, Password, Language from Users where Id = '".dbEscape($uid)."'" ); + + $types = array(); + $changes = getFormChanges( $dbUser, $_REQUEST['newUser'], $types ); + + if ( !empty($_REQUEST['newUser']['Password']) ) + $changes['Password'] = "Password = password('".dbEscape($_REQUEST['newUser']['Password'])."')"; + else + unset( $changes['Password'] ); + if ( count( $changes ) ) + { + $sql = "update Users set ".implode( ", ", $changes )." where Id = '".dbEscape($uid)."'"; + dbQuery( $sql ); + $refreshParent = true; + } + $view = 'none'; + } + } + + if ( $action == "reset" ) + { + $_SESSION['zmEventResetTime'] = strftime( STRF_FMT_DATETIME_DB ); + setcookie( "zmEventResetTime", $_SESSION['zmEventResetTime'], time()+3600*24*30*12*10 ); + //if ( $cookies ) session_write_close(); + } +} + +?> diff --git a/web/includes/config.php b/web/includes/config.php new file mode 100644 index 000000000..6f1082473 --- /dev/null +++ b/web/includes/config.php @@ -0,0 +1,173 @@ + 0 ) +{ + if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) ) + print( "Warning, overriding installed $localConfigFile file with local copy\n" ); + else + error_log( "Warning, overriding installed $localConfigFile file with local copy" ); + $configFile = $localConfigFile; +} + +$cfg = fopen( $configFile, "r") or die("Could not open config file."); +while ( !feof($cfg) ) +{ + $str = fgets( $cfg, 256 ); + if ( preg_match( '/^\s*$/', $str )) + continue; + elseif ( preg_match( '/^\s*#/', $str )) + continue; + elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.+?)\s*$/', $str, $matches )) + define( $matches[1], $matches[2] ); +} +fclose( $cfg ); + +// +// This section is options normally derived from other options or configuration +// +define( "ZMU_PATH", ZM_PATH_BIN."/zmu" ); // Local path to the ZoneMinder Utility + +// +// If setup supports Video 4 Linux v2 and/or v1 +// +define( "ZM_HAS_V4L2", "1" ); // V4L2 support enabled +define( "ZM_HAS_V4L1", "0" ); // V4L1 support enabled +define( "ZM_HAS_V4L", "1" ); // V4L support enabled + +// +// If PCRE dev libraries are installed +// +define( "ZM_PCRE", "1" ); // PCRE support enabled + +// +// Alarm states +// +define( "STATE_IDLE", 0 ); +define( "STATE_PREALARM", 1 ); +define( "STATE_ALARM", 2 ); +define( "STATE_ALERT", 3 ); +define( "STATE_TAPE", 4 ); + +// +// DVR Control Commands +// + +define( "MSG_CMD", 1 ); +define( "MSG_DATA_WATCH", 2 ); +define( "MSG_DATA_EVENT", 3 ); + +define( "CMD_NONE", 0 ); +define( "CMD_PAUSE", 1 ); +define( "CMD_PLAY", 2 ); +define( "CMD_STOP", 3 ); +define( "CMD_FASTFWD", 4 ); +define( "CMD_SLOWFWD", 5 ); +define( "CMD_SLOWREV", 6 ); +define( "CMD_FASTREV", 7 ); +define( "CMD_ZOOMIN", 8 ); +define( "CMD_ZOOMOUT", 9 ); +define( "CMD_PAN", 10 ); +define( "CMD_SCALE", 11 ); +define( "CMD_PREV", 12 ); +define( "CMD_NEXT", 13 ); +define( "CMD_SEEK", 14 ); +define( "CMD_VARPLAY", 15 ); +define( "CMD_QUERY", 99 ); + +// +// These are miscellaneous options you won't normally need to change +// +define( "MAX_EVENTS", 10 ); // The maximum number of events to show in the monitor event listing +define( "RATE_BASE", 100 ); // The additional scaling factor used to help get fractional rates in integer format +define( "SCALE_BASE", 100 ); // The additional scaling factor used to help get fractional scales in integer format + +// +// Date and time formats, eventually some of these may end up in the language files +// +define( "DATE_FMT_CONSOLE_LONG", "D jS M, g:ia" ); // This is the main console date/time, date() or strftime() format +define( "DATE_FMT_CONSOLE_SHORT", "%H:%M" ); // This is the xHTML console date/time, date() or strftime() format + +define( "STRF_FMT_DATETIME_DB", "%Y-%m-%d %H:%M:%S" ); // Strftime format for database queries, don't change + +define( "STRF_FMT_DATETIME", "%c" ); // Strftime locale aware format for dates with times +define( "STRF_FMT_DATE", "%x" ); // Strftime locale aware format for dates without times +define( "STRF_FMT_TIME", "%X" ); // Strftime locale aware format for times without dates + +define( "STRF_FMT_DATETIME_SHORT", "%y/%m/%d %H:%M:%S" ); // Strftime shorter format for dates with time, not locale aware +define( "STRF_FMT_DATETIME_SHORTER", "%m/%d %H:%M:%S" ); // Strftime shorter format for dates with time, not locale aware, used where space is tight + +define( "MYSQL_FMT_DATETIME_SHORT", "%y/%m/%d %H:%i:%S" ); // MySQL date_format shorter format for dates with time + +require_once( 'database.php' ); +loadConfig(); + +$GLOBALS['defaultUser'] = array( + "Username" => "admin", + "Password" => "", + "Language" => "", + "Enabled" => 1, + "Stream" => 'View', + "Events" => 'Edit', + "Control" => 'Edit', + "Monitors" => 'Edit', + "Devices" => 'Edit', + "System" => 'Edit', + "MaxBandwidth" => "", + "MonitorIds" => false +); + +function loadConfig( $defineConsts=true ) +{ + global $config; + global $configCats; + + $config = array(); + $configCat = array(); + + $sql = "select * from Config order by Id asc"; + $result = mysql_query( $sql ); + if ( !$result ) + echo mysql_error(); + $monitors = array(); + while( $row = mysql_fetch_assoc( $result ) ) + { + if ( $defineConsts ) + define( $row['Name'], $row['Value'] ); + $config[$row['Name']] = $row; + if ( !($configCat = &$configCats[$row['Category']]) ) + { + $configCats[$row['Category']] = array(); + $configCat = &$configCats[$row['Category']]; + } + $configCat[$row['Name']] = $row; + } + //print_r( $config ); + //print_r( $configCats ); +} + +?> diff --git a/web/includes/config.php.in b/web/includes/config.php.in new file mode 100644 index 000000000..b9f66449e --- /dev/null +++ b/web/includes/config.php.in @@ -0,0 +1,173 @@ + 0 ) +{ + if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) ) + print( "Warning, overriding installed $localConfigFile file with local copy\n" ); + else + error_log( "Warning, overriding installed $localConfigFile file with local copy" ); + $configFile = $localConfigFile; +} + +$cfg = fopen( $configFile, "r") or die("Could not open config file."); +while ( !feof($cfg) ) +{ + $str = fgets( $cfg, 256 ); + if ( preg_match( '/^\s*$/', $str )) + continue; + elseif ( preg_match( '/^\s*#/', $str )) + continue; + elseif ( preg_match( '/^\s*([^=\s]+)\s*=\s*(.+?)\s*$/', $str, $matches )) + define( $matches[1], $matches[2] ); +} +fclose( $cfg ); + +// +// This section is options normally derived from other options or configuration +// +define( "ZMU_PATH", ZM_PATH_BIN."/zmu" ); // Local path to the ZoneMinder Utility + +// +// If setup supports Video 4 Linux v2 and/or v1 +// +define( "ZM_HAS_V4L2", "@ZM_HAS_V4L2@" ); // V4L2 support enabled +define( "ZM_HAS_V4L1", "@ZM_HAS_V4L1@" ); // V4L1 support enabled +define( "ZM_HAS_V4L", "@ZM_HAS_V4L@" ); // V4L support enabled + +// +// If PCRE dev libraries are installed +// +define( "ZM_PCRE", "@ZM_PCRE@" ); // PCRE support enabled + +// +// Alarm states +// +define( "STATE_IDLE", 0 ); +define( "STATE_PREALARM", 1 ); +define( "STATE_ALARM", 2 ); +define( "STATE_ALERT", 3 ); +define( "STATE_TAPE", 4 ); + +// +// DVR Control Commands +// + +define( "MSG_CMD", 1 ); +define( "MSG_DATA_WATCH", 2 ); +define( "MSG_DATA_EVENT", 3 ); + +define( "CMD_NONE", 0 ); +define( "CMD_PAUSE", 1 ); +define( "CMD_PLAY", 2 ); +define( "CMD_STOP", 3 ); +define( "CMD_FASTFWD", 4 ); +define( "CMD_SLOWFWD", 5 ); +define( "CMD_SLOWREV", 6 ); +define( "CMD_FASTREV", 7 ); +define( "CMD_ZOOMIN", 8 ); +define( "CMD_ZOOMOUT", 9 ); +define( "CMD_PAN", 10 ); +define( "CMD_SCALE", 11 ); +define( "CMD_PREV", 12 ); +define( "CMD_NEXT", 13 ); +define( "CMD_SEEK", 14 ); +define( "CMD_VARPLAY", 15 ); +define( "CMD_QUERY", 99 ); + +// +// These are miscellaneous options you won't normally need to change +// +define( "MAX_EVENTS", 10 ); // The maximum number of events to show in the monitor event listing +define( "RATE_BASE", 100 ); // The additional scaling factor used to help get fractional rates in integer format +define( "SCALE_BASE", 100 ); // The additional scaling factor used to help get fractional scales in integer format + +// +// Date and time formats, eventually some of these may end up in the language files +// +define( "DATE_FMT_CONSOLE_LONG", "D jS M, g:ia" ); // This is the main console date/time, date() or strftime() format +define( "DATE_FMT_CONSOLE_SHORT", "%H:%M" ); // This is the xHTML console date/time, date() or strftime() format + +define( "STRF_FMT_DATETIME_DB", "%Y-%m-%d %H:%M:%S" ); // Strftime format for database queries, don't change + +define( "STRF_FMT_DATETIME", "%c" ); // Strftime locale aware format for dates with times +define( "STRF_FMT_DATE", "%x" ); // Strftime locale aware format for dates without times +define( "STRF_FMT_TIME", "%X" ); // Strftime locale aware format for times without dates + +define( "STRF_FMT_DATETIME_SHORT", "%y/%m/%d %H:%M:%S" ); // Strftime shorter format for dates with time, not locale aware +define( "STRF_FMT_DATETIME_SHORTER", "%m/%d %H:%M:%S" ); // Strftime shorter format for dates with time, not locale aware, used where space is tight + +define( "MYSQL_FMT_DATETIME_SHORT", "%y/%m/%d %H:%i:%S" ); // MySQL date_format shorter format for dates with time + +require_once( 'database.php' ); +loadConfig(); + +$GLOBALS['defaultUser'] = array( + "Username" => "admin", + "Password" => "", + "Language" => "", + "Enabled" => 1, + "Stream" => 'View', + "Events" => 'Edit', + "Control" => 'Edit', + "Monitors" => 'Edit', + "Devices" => 'Edit', + "System" => 'Edit', + "MaxBandwidth" => "", + "MonitorIds" => false +); + +function loadConfig( $defineConsts=true ) +{ + global $config; + global $configCats; + + $config = array(); + $configCat = array(); + + $sql = "select * from Config order by Id asc"; + $result = mysql_query( $sql ); + if ( !$result ) + echo mysql_error(); + $monitors = array(); + while( $row = mysql_fetch_assoc( $result ) ) + { + if ( $defineConsts ) + define( $row['Name'], $row['Value'] ); + $config[$row['Name']] = $row; + if ( !($configCat = &$configCats[$row['Category']]) ) + { + $configCats[$row['Category']] = array(); + $configCat = &$configCats[$row['Category']]; + } + $configCat[$row['Name']] = $row; + } + //print_r( $config ); + //print_r( $configCats ); +} + +?> diff --git a/web/includes/control_functions.php b/web/includes/control_functions.php new file mode 100644 index 000000000..a4549155e --- /dev/null +++ b/web/includes/control_functions.php @@ -0,0 +1,969 @@ + array( + 'Up' => 'Left', + 'Down' => 'Right', + 'Left' => 'Down', + 'Right' => 'Up', + 'UpLeft' => 'DownLeft', + 'UpRight' => 'UpLeft', + 'DownLeft' => 'DownRight', + 'DownRight' => 'UpRight', + ), + '180' => array( + 'Up' => 'Down', + 'Down' => 'Up', + 'Left' => 'Right', + 'Right' => 'Left', + 'UpLeft' => 'DownRight', + 'UpRight' => 'DownLeft', + 'DownLeft' => 'UpRight', + 'DownRight' => 'UpLeft', + ), + '270' => array( + 'Up' => 'Right', + 'Down' => 'Left', + 'Left' => 'Up', + 'Right' => 'Down', + 'UpLeft' => 'UpRight', + 'UpRight' => 'DownRight', + 'DownLeft' => 'UpLeft', + 'DownRight' => 'DownLeft', + ), + 'hori' => array( + 'Up' => 'Up', + 'Down' => 'Down', + 'Left' => 'Right', + 'Right' => 'Left', + 'UpLeft' => 'UpRight', + 'UpRight' => 'UpLeft', + 'DownLeft' => 'DownRight', + 'DownRight' => 'DownLeft', + ), + 'vert' => array( + 'Up' => 'Down', + 'Down' => 'Up', + 'Left' => 'Left', + 'Right' => 'Right', + 'UpLeft' => 'DownLeft', + 'UpRight' => 'DownRight', + 'DownLeft' => 'UpLeft', + 'DownRight' => 'UpRight', + ), + ); + $new_dirn = $conversions[$monitor['Orientation']][$dirn]; + $_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] ); + $dirn = $new_dirn; + } + + if ( $monitor['HasPanSpeed'] && $xFactor ) + { + if ( $monitor['HasTurboPan'] ) + { + if ( $xFactor >= $turbo ) + { + $panSpeed = $monitor['TurboPanSpeed']; + } + else + { + $xFactor = $xFactor/$turbo; + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + else + { + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + $ctrlCommand .= " --panspeed=".$panSpeed; + } + if ( $monitor['HasTiltSpeed'] && $yFactor ) + { + if ( $monitor['HasTurboTilt'] ) + { + if ( $yFactor >= $turbo ) + { + $tiltSpeed = $monitor['TurboTiltSpeed']; + } + else + { + $yFactor = $yFactor/$turbo; + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + else + { + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + $ctrlCommand .= " --tiltspeed=".$tiltSpeed; + } + switch( $mode ) + { + case 'Rel' : + case 'Abs' : + { + if ( preg_match( '/(Left|Right)$/', $dirn ) ) + { + $panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); + $ctrlCommand .= " --panstep=".$panStep; + } + if ( preg_match( '/^(Up|Down)/', $dirn ) ) + { + $tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); + $ctrlCommand .= " --tiltstep=".$tiltStep; + } + break; + } + case 'Con' : + { + if ( $monitor['AutoStopTimeout'] ) + { + $slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); + $slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); + if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) + { + $ctrlCommand .= " --autostop"; + } + } + break; + } + } + } + } + } + } + elseif ( isset($_REQUEST['x']) && isset($_REQUEST['y']) ) + { + if ( $_REQUEST['control'] == "moveMap" ) + { + $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); + $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); + switch ( $monitor['Orientation'] ) + { + case '0' : + case '180' : + case 'hori' : + case 'vert' : + $width = $monitor['Width']; + $height = $monitor['Height']; + break; + case '90' : + case '270' : + $width = $monitor['Height']; + $height = $monitor['Width']; + break; + } + switch ( $monitor['Orientation'] ) + { + case '90' : + $tempY = $y; + $y = $height - $x; + $x = $tempY; + break; + case '180' : + $x = $width - $x; + $y = $height - $y; + break; + case '270' : + $tempX = $x; + $x = $width - $y; + $y = $tempX; + break; + case 'hori' : + $x = $width - $x; + break; + case 'vert' : + $y = $height - $y; + break; + } + //$ctrlCommand .= " --xcoord=$x --ycoord=$y --width=$width --height=$height"; + $ctrlCommand .= " --xcoord=$x --ycoord=$y"; + } + elseif ( $_REQUEST['control'] == "movePseudoMap" ) + { + $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); + $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); + + $halfWidth = $monitor['Width'] / 2; + $halfHeight = $monitor['Height'] / 2; + $xFactor = ($x - $halfWidth)/$halfWidth; + $yFactor = ($y - $halfHeight)/$halfHeight; + + switch ( $monitor['Orientation'] ) + { + case '90' : + $tempYFactor = $y; + $yFactor = -$xFactor; + $xFactor = $tempYFactor; + break; + case '180' : + $xFactor = -$xFactor; + $yFactor = -$yFactor; + break; + case '270' : + $tempXFactor = $x; + $xFactor = -$yFactor; + $yFactor = $tempXFactor; + break; + case 'hori' : + $xFactor = -$xFactor; + break; + case 'vert' : + $yFactor = -$yFactor; + break; + } + + $turbo = 0.9; // Threshold for turbo speed + $blind = 0.1; // Threshold for blind spot + + $panControl = ''; + $tiltControl = ''; + if ( $xFactor > $blind ) + { + $panControl = 'Right'; + } + elseif ( $xFactor < -$blind ) + { + $panControl = 'Left'; + } + if ( $yFactor > $blind ) + { + $tiltControl = 'Down'; + } + elseif ( $yFactor < -$blind ) + { + $tiltControl = 'Up'; + } + + $dirn = $tiltControl.$panControl; + if ( !$dirn ) + { + // No command, probably in blind spot in middle + $_REQUEST['control'] = 'null'; + return( false ); + } + else + { + $_REQUEST['control'] = 'moveRel'.$dirn; + $xFactor = abs($xFactor); + $yFactor = abs($yFactor); + + if ( $monitor['HasPanSpeed'] && $xFactor ) + { + if ( $monitor['HasTurboPan'] ) + { + if ( $xFactor >= $turbo ) + { + $panSpeed = $monitor['TurboPanSpeed']; + } + else + { + $xFactor = $xFactor/$turbo; + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + else + { + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + if ( $monitor['HasTiltSpeed'] && $yFactor ) + { + if ( $monitor['HasTurboTilt'] ) + { + if ( $yFactor >= $turbo ) + { + $tiltSpeed = $monitor['TurboTiltSpeed']; + } + else + { + $yFactor = $yFactor/$turbo; + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + else + { + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + if ( preg_match( '/(Left|Right)$/', $dirn ) ) + { + $panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); + $ctrlCommand .= " --panstep=".$panStep." --panspeed=".$panSpeed; + } + if ( preg_match( '/^(Up|Down)/', $dirn ) ) + { + $tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); + $ctrlCommand .= " --tiltstep=".$tiltStep." --tiltspeed=".$tiltSpeed; + } + } + } + elseif ( $_REQUEST['control'] == "moveConMap" ) + { + $x = deScale( $_REQUEST['x'], $_REQUEST['scale'] ); + $y = deScale( $_REQUEST['y'], $_REQUEST['scale'] ); + + $halfWidth = $monitor['Width'] / 2; + $halfHeight = $monitor['Height'] / 2; + $xFactor = ($x - $halfWidth)/$halfWidth; + $yFactor = ($y - $halfHeight)/$halfHeight; + + switch ( $monitor['Orientation'] ) + { + case '90' : + $tempYFactor = $y; + $yFactor = -$xFactor; + $xFactor = $tempYFactor; + break; + case '180' : + $xFactor = -$xFactor; + $yFactor = -$yFactor; + break; + case '270' : + $tempXFactor = $x; + $xFactor = -$yFactor; + $yFactor = $tempXFactor; + break; + case 'hori' : + $xFactor = -$xFactor; + break; + case 'vert' : + $yFactor = -$yFactor; + break; + } + + $slow = 0.9; // Threshold for slow speed/timeouts + $turbo = 0.9; // Threshold for turbo speed + $blind = 0.1; // Threshold for blind spot + + $panControl = ''; + $tiltControl = ''; + if ( $xFactor > $blind ) + { + $panControl = 'Right'; + } + elseif ( $xFactor < -$blind ) + { + $panControl = 'Left'; + } + if ( $yFactor > $blind ) + { + $tiltControl = 'Down'; + } + elseif ( $yFactor < -$blind ) + { + $tiltControl = 'Up'; + } + + $dirn = $tiltControl.$panControl; + if ( !$dirn ) + { + // No command, probably in blind spot in middle + $_REQUEST['control'] = 'moveStop'; + } + else + { + $_REQUEST['control'] = 'moveCon'.$dirn; + $xFactor = abs($xFactor); + $yFactor = abs($yFactor); + + if ( $monitor['HasPanSpeed'] && $xFactor ) + { + if ( $monitor['HasTurboPan'] ) + { + if ( $xFactor >= $turbo ) + { + $panSpeed = $monitor['TurboPanSpeed']; + } + else + { + $xFactor = $xFactor/$turbo; + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + else + { + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + if ( $monitor['HasTiltSpeed'] && $yFactor ) + { + if ( $monitor['HasTurboTilt'] ) + { + if ( $yFactor >= $turbo ) + { + $tiltSpeed = $monitor['TurboTiltSpeed']; + } + else + { + $yFactor = $yFactor/$turbo; + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + else + { + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + if ( preg_match( '/(Left|Right)$/', $dirn ) ) + { + $ctrlCommand .= " --panspeed=".$panSpeed; + } + if ( preg_match( '/^(Up|Down)/', $dirn ) ) + { + $ctrlCommand .= " --tiltspeed=".$tiltSpeed; + } + if ( $monitor['AutoStopTimeout'] ) + { + $slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); + $slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); + if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) + { + $ctrlCommand .= " --autostop"; + } + } + } + } + else + { + $slow = 0.9; // Threshold for slow speed/timeouts + $turbo = 0.9; // Threshold for turbo speed + $long_y = 48; + $short_x = 32; + $short_y = 32; + + if ( preg_match( '/^([a-z]+)([A-Z][a-z]+)([A-Z][a-z]+)$/', $_REQUEST['control'], $matches ) ) + { + $command = $matches[1]; + $mode = $matches[2]; + $dirn = $matches[3]; + + switch( $command ) + { + case 'focus' : + { + switch( $dirn ) + { + case 'Near' : + { + $factor = ($long_y-($y+1))/$long_y; + break; + } + case 'Far' : + { + $factor = ($y+1)/$long_y; + break; + } + } + if ( $monitor['HasFocusSpeed'] ) + { + $speed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$factor))); + $ctrlCommand .= " --speed=".$speed; + } + switch( $mode ) + { + case 'Abs' : + case 'Rel' : + { + $step = intval(round($monitor['MinFocusStep']+(($monitor['MaxFocusStep']-$monitor['MinFocusStep'])*$factor))); + $ctrlCommand .= " --step=".$step; + break; + } + case 'Con' : + { + if ( $monitor['AutoStopTimeout'] ) + { + $slowSpeed = intval(round($monitor['MinFocusSpeed']+(($monitor['MaxFocusSpeed']-$monitor['MinFocusSpeed'])*$slow))); + if ( $speed < $slowSpeed ) + { + $ctrlCommand .= " --autostop"; + } + } + break; + } + } + break; + } + case 'zoom' : + { + switch( $dirn ) + { + case 'Tele' : + { + $factor = ($long_y-($y+1))/$long_y; + break; + } + case 'Wide' : + { + $factor = ($y+1)/$long_y; + break; + } + } + if ( $monitor['HasZoomSpeed'] ) + { + $speed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$factor))); + $ctrlCommand .= " --speed=".$speed; + } + switch( $mode ) + { + case 'Abs' : + case 'Rel' : + { + $step = intval(round($monitor['MinZoomStep']+(($monitor['MaxZoomStep']-$monitor['MinZoomStep'])*$factor))); + $ctrlCommand .= " --step=".$step; + break; + } + case 'Con' : + { + if ( $monitor['AutoStopTimeout'] ) + { + $slowSpeed = intval(round($monitor['MinZoomSpeed']+(($monitor['MaxZoomSpeed']-$monitor['MinZoomSpeed'])*$slow))); + if ( $speed < $slowSpeed ) + { + $ctrlCommand .= " --autostop"; + } + } + break; + } + } + break; + } + case 'iris' : + { + switch( $dirn ) + { + case 'Open' : + { + $factor = ($long_y-($y+1))/$long_y; + break; + } + case 'Close' : + { + $factor = ($y+1)/$long_y; + break; + } + } + if ( $monitor['HasIrisSpeed'] ) + { + $speed = intval(round($monitor['MinIrisSpeed']+(($monitor['MaxIrisSpeed']-$monitor['MinIrisSpeed'])*$factor))); + $ctrlCommand .= " --speed=".$speed; + } + switch( $mode ) + { + case 'Abs' : + case 'Rel' : + { + $step = intval(round($monitor['MinIrisStep']+(($monitor['MaxIrisStep']-$monitor['MinIrisStep'])*$factor))); + $ctrlCommand .= " --step=".$step; + break; + } + } + break; + } + case 'white' : + { + switch( $dirn ) + { + case 'In' : + { + $factor = ($long_y-($y+1))/$long_y; + break; + } + case 'Out' : + { + $factor = ($y+1)/$long_y; + break; + } + } + if ( $monitor['HasWhiteSpeed'] ) + { + $speed = intval(round($monitor['MinWhiteSpeed']+(($monitor['MaxWhiteSpeed']-$monitor['MinWhiteSpeed'])*$factor))); + $ctrlCommand .= " --speed=".$speed; + } + switch( $mode ) + { + case 'Abs' : + case 'Rel' : + { + $step = intval(round($monitor['MinWhiteStep']+(($monitor['MaxWhiteStep']-$monitor['MinWhiteStep'])*$factor))); + $ctrlCommand .= " --step=".$step; + break; + } + } + break; + } + case 'gain' : + { + switch( $dirn ) + { + case 'Up' : + { + $factor = ($long_y-($y+1))/$long_y; + break; + } + case 'Down' : + { + $factor = ($y+1)/$long_y; + break; + } + } + if ( $monitor['HasGainSpeed'] ) + { + $speed = intval(round($monitor['MinGainSpeed']+(($monitor['MaxGainSpeed']-$monitor['MinGainSpeed'])*$factor))); + $ctrlCommand .= " --speed=".$speed; + } + switch( $mode ) + { + case 'Abs' : + case 'Rel' : + { + $step = intval(round($monitor['MinGainStep']+(($monitor['MaxGainStep']-$monitor['MinGainStep'])*$factor))); + $ctrlCommand .= " --step=".$step; + break; + } + } + break; + } + case 'move' : + { + $xFactor = 0; + $yFactor = 0; + + if ( preg_match( '/^Up/', $dirn ) ) + { + $yFactor = ($short_y-($y+1))/$short_y; + } + elseif ( preg_match( '/^Down/', $dirn ) ) + { + $yFactor = ($y+1)/$short_y; + } + if ( preg_match( '/Left$/', $dirn ) ) + { + $xFactor = ($short_x-($x+1))/$short_x; + } + elseif ( preg_match( '/Right$/', $dirn ) ) + { + $xFactor = ($x+1)/$short_x; + } + + if ( $monitor['Orientation'] != '0' ) + { + $conversions = array( + '90' => array( + 'Up' => 'Left', + 'Down' => 'Right', + 'Left' => 'Down', + 'Right' => 'Up', + 'UpLeft' => 'DownLeft', + 'UpRight' => 'UpLeft', + 'DownLeft' => 'DownRight', + 'DownRight' => 'UpRight', + ), + '180' => array( + 'Up' => 'Down', + 'Down' => 'Up', + 'Left' => 'Right', + 'Right' => 'Left', + 'UpLeft' => 'DownRight', + 'UpRight' => 'DownLeft', + 'DownLeft' => 'UpRight', + 'DownRight' => 'UpLeft', + ), + '270' => array( + 'Up' => 'Right', + 'Down' => 'Left', + 'Left' => 'Up', + 'Right' => 'Down', + 'UpLeft' => 'UpRight', + 'UpRight' => 'DownRight', + 'DownLeft' => 'UpLeft', + 'DownRight' => 'DownLeft', + ), + 'hori' => array( + 'Up' => 'Up', + 'Down' => 'Down', + 'Left' => 'Right', + 'Right' => 'Left', + 'UpLeft' => 'UpRight', + 'UpRight' => 'UpLeft', + 'DownLeft' => 'DownRight', + 'DownRight' => 'DownLeft', + ), + 'vert' => array( + 'Up' => 'Down', + 'Down' => 'Up', + 'Left' => 'Left', + 'Right' => 'Right', + 'UpLeft' => 'DownLeft', + 'UpRight' => 'DownRight', + 'DownLeft' => 'UpLeft', + 'DownRight' => 'UpRight', + ), + ); + $new_dirn = $conversions[$monitor['Orientation']][$dirn]; + $_REQUEST['control'] = preg_replace( "/_$dirn\$/", "_$new_dirn", $_REQUEST['control'] ); + $dirn = $new_dirn; + } + + if ( $monitor['HasPanSpeed'] && $xFactor ) + { + if ( $monitor['HasTurboPan'] ) + { + if ( $xFactor >= $turbo ) + { + $panSpeed = $monitor['TurboPanSpeed']; + } + else + { + $xFactor = $xFactor/$turbo; + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + } + else + { + $panSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$xFactor))); + } + $ctrlCommand .= " --panspeed=".$panSpeed; + } + if ( $monitor['HasTiltSpeed'] && $yFactor ) + { + if ( $monitor['HasTurboTilt'] ) + { + if ( $yFactor >= $turbo ) + { + $tiltSpeed = $monitor['TurboTiltSpeed']; + } + else + { + $yFactor = $yFactor/$turbo; + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + } + else + { + $tiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$yFactor))); + } + $ctrlCommand .= " --tiltspeed=".$tiltSpeed; + } + switch( $mode ) + { + case 'Rel' : + case 'Abs' : + { + if ( preg_match( '/(Left|Right)$/', $dirn ) ) + { + $panStep = intval(round($monitor['MinPanStep']+(($monitor['MaxPanStep']-$monitor['MinPanStep'])*$xFactor))); + $ctrlCommand .= " --panstep=".$panStep; + } + if ( preg_match( '/^(Up|Down)/', $dirn ) ) + { + $tiltStep = intval(round($monitor['MinTiltStep']+(($monitor['MaxTiltStep']-$monitor['MinTiltStep'])*$yFactor))); + $ctrlCommand .= " --tiltstep=".$tiltStep; + } + break; + } + case 'Con' : + { + if ( $monitor['AutoStopTimeout'] ) + { + $slowPanSpeed = intval(round($monitor['MinPanSpeed']+(($monitor['MaxPanSpeed']-$monitor['MinPanSpeed'])*$slow))); + $slowTiltSpeed = intval(round($monitor['MinTiltSpeed']+(($monitor['MaxTiltSpeed']-$monitor['MinTiltSpeed'])*$slow))); + if ( (!isset($panSpeed) || ($panSpeed < $slowPanSpeed)) && (!isset($tiltSpeed) || ($tiltSpeed < $slowTiltSpeed)) ) + { + $ctrlCommand .= " --autostop"; + } + } + break; + } + } + } + } + } + } + } + else + { + if ( preg_match( '/^presetGoto(\d+)$/', $_REQUEST['control'], $matches ) ) + { + $_REQUEST['control'] = 'presetGoto'; + $ctrlCommand .= " --preset=".$matches[1]; + } + elseif ( $_REQUEST['control'] == "presetGoto" && !empty($_REQUEST['preset']) ) + { + $ctrlCommand .= " --preset=".$_REQUEST['preset']; + } + elseif ( $_REQUEST['control'] == "presetSet" ) + { + if ( canEdit( 'Control' ) ) + { + $preset = validInt($_REQUEST['preset']); + $newLabel = validJsStr($_REQUEST['newLabel']); + $row = dbFetchOne( "select * from ControlPresets where MonitorId = '".$monitor['Id']."' and Preset = '".dbEscape($preset)."'" ); + if ( $newLabel != $row['Label'] ) + { + if ( $newLabel ) + $sql = "replace into ControlPresets ( MonitorId, Preset, Label ) values ( '".$monitor['Id']."', '".dbEscape($preset)."', '".dbEscape($newLabel)."' )"; + else + $sql = "delete from ControlPresets where MonitorId = '".$monitor['Id']."' and Preset = '".dbEscape($preset)."'"; + dbQuery( $sql ); + } + $ctrlCommand .= " --preset=".$preset; + } + $ctrlCommand .= " --preset=".$preset; + } + elseif ( $_REQUEST['control'] == "moveMap" ) + { + $ctrlCommand .= " --xcoord=$x --ycoord=$y"; + } + } + $ctrlCommand .= " --command=".$_REQUEST['control']; + return( $ctrlCommand ); +} diff --git a/web/includes/database.php b/web/includes/database.php new file mode 100644 index 000000000..314029b20 --- /dev/null +++ b/web/includes/database.php @@ -0,0 +1,350 @@ += DB_LOG_DEBUG); + if ( $dbLogLevel > DB_LOG_OFF ) + Debug( "SQL-LOG: $sql".($noExecute?" (not executed)":"") ); + return( $noExecute ); +} + +function dbError( $sql ) +{ + Fatal( "SQL-ERR '".mysql_error()."', statement was '".$sql."'" ); +} + +function dbEscape( $string ) +{ + if ( version_compare( phpversion(), "4.3.0", "<") ) + if ( get_magic_quotes_gpc() ) + return( mysql_escape_string( stripslashes( $string ) ) ); + else + return( mysql_escape_string( $string ) ); + else + if ( get_magic_quotes_gpc() ) + return( mysql_real_escape_string( stripslashes( $string ) ) ); + else + return( mysql_real_escape_string( $string ) ); +} + +function dbQuery( $sql ) +{ + if ( dbLog( $sql, true ) ) + return; + if (!($result = mysql_query( $sql ))) + dbError( $sql ); + return( $result ); +} + +function dbFetchOne( $sql, $col=false ) +{ + dbLog( $sql ); + if (!($result = mysql_query( $sql ))) + dbError( $sql ); + + if ( $dbRow = mysql_fetch_assoc( $result ) ) + return( $col?$dbRow[$col]:$dbRow ); + return( false ); +} + +function dbFetchAll( $sql, $col=false ) +{ + dbLog( $sql ); + if (!($result = mysql_query( $sql ))) + dbError( $sql ); + + $dbRows = array(); + while( $dbRow = mysql_fetch_assoc( $result ) ) + $dbRows[] = $col?$dbRow[$col]:$dbRow; + return( $dbRows ); +} + +function dbFetchAssoc( $sql, $indexCol, $dataCol=false ) +{ + dbLog( $sql ); + if (!($result = mysql_query( $sql ))) + dbError( $sql ); + + $dbRows = array(); + while( $dbRow = mysql_fetch_assoc( $result ) ) + $dbRows[$dbRow[$indexCol]] = $dataCol?$dbRow[$dataCol]:$dbRow; + return( $dbRows ); +} + +function dbFetch( $sql, $col=false ) +{ + return( dbFetchAll( $sql, $col ) ); +} + +function dbFetchNext( $result, $col=false ) +{ + if ( $dbRow = mysql_fetch_assoc( $result ) ) + return( $col?$dbRow[$col]:$dbRow ); + return( false ); +} + +function dbNumRows( $sql ) +{ + dbLog( $sql ); + if (!($result = mysql_query( $sql ))) + dbError( $sql ); + return( mysql_num_rows( $result ) ); +} + +function dbInsertId() +{ + return( mysql_insert_id() ); +} + +function getEnumValues( $table, $column ) +{ + $row = dbFetchOne( "describe $table $column" ); + preg_match_all( "/'([^']+)'/", $row['Type'], $matches ); + return( $matches[1] ); +} + +function getSetValues( $table, $column ) +{ + return( getEnumValues( $table, $column ) ); +} + +function getUniqueValues( $table, $column, $asString=1 ) +{ + $values = array(); + $sql = "select distinct $column from $table where (not isnull($column) and $column != '') order by $column"; + foreach( dbFetchAll( $sql ) as $row ) + { + if ( $asString ) + $values[$row[$column]] = $row[$column]; + else + $values[] = $row[$column]; + } + return( $values ); +} + +function getTableColumns( $table, $asString=1 ) +{ + $columns = array(); + $table = dbEscape($table); + $sql = "describe $table"; + foreach( dbFetchAll( $sql ) as $row ) + { + if ( $asString ) + $columns[$row['Field']] = $row['Type']; + else + $columns[] = $row['Type']; + } + return( $columns ); +} + +function getTableAutoInc( $table ) +{ + $sql = "show table status where Name = '".dbEscape($table)."'"; + $row = dbFetchOne( $sql ); + return( $row['Auto_increment'] ); +} + +function getTableDescription( $table, $asString=1 ) +{ + $columns = array(); + $table = dbEscape($table); + $sql = "describe $table"; + foreach( dbFetchAll( $sql ) as $row ) + { + $desc = array( + 'name' => $row['Field'], + 'required' => ($row['Null']=='NO')?true:false, + 'default' => $row['Default'], + 'db' => $row, + ); + if ( preg_match( "/^varchar\((\d+)\)$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'text'; + $desc['typeAttrib'] = 'varchar'; + $desc['maxLength'] = $matches[1]; + } + elseif ( preg_match( "/^(\w+)?text$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'text'; + if (!empty($matches[1]) ) + $desc['typeAttrib'] = $matches[1]; + switch ( $matches[1] ) + { + case 'tiny' : + $desc['maxLength'] = 255; + break; + case 'medium' : + $desc['maxLength'] = 32768; + break; + case '' : + case 'big' : + //$desc['minLength'] = -128; + break; + default : + Error( "Unexpected text qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" ); + break; + } + } + elseif ( preg_match( "/^(enum|set)\((.*)\)$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'text'; + $desc['typeAttrib'] = $matches[1]; + preg_match_all( "/'([^']+)'/", $matches[2], $matches ); + $desc['values'] = $matches[1]; + } + elseif ( preg_match( "/^(\w+)?int\(\d+\)(?:\s+(unsigned))?$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'integer'; + switch ( $matches[1] ) + { + case 'tiny' : + $desc['minValue'] = -128; + $desc['maxValue'] = 127; + break; + case 'small' : + $desc['minValue'] = -32768; + $desc['maxValue'] = 32767; + break; + case 'medium' : + $desc['minValue'] = -8388608; + $desc['maxValue'] = 8388607; + break; + case '' : + $desc['minValue'] = -2147483648; + $desc['maxValue'] = 2147483647; + break; + case 'big' : + //$desc['minValue'] = -128; + //$desc['maxValue'] = 127; + break; + default : + Error( "Unexpected integer qualifier '".$matches[1]."' found for field '".$row['Field']."' in table '".$table."'" ); + break; + } + if ( !empty($matches[1]) ) + $desc['typeAttrib'] = $matches[1]; + if ( $desc['unsigned'] = ( isset($matches[2]) && $matches[2] == 'unsigned' ) ) + { + $desc['maxValue'] += (-$desc['minValue']); + $desc['minValue'] = 0; + } + } + elseif ( preg_match( "/^(?:decimal|numeric)\((\d+)(?:,(\d+))?\)(?:\s+(unsigned))?$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'fixed'; + $desc['range'] = $matches[1]; + if ( isset($matches[2]) ) + $desc['precision'] = $matches[2]; + else + $desc['precision'] = 0; + $desc['unsigned'] = ( isset($matches[3]) && $matches[3] == 'unsigned' ); + } + elseif ( preg_match( "/^(datetime|timestamp|date|time)$/", $row['Type'], $matches ) ) + { + $desc['type'] = 'datetime'; + switch ( $desc['typeAttrib'] = $matches[1] ) + { + case 'datetime' : + case 'timestamp' : + $desc['hasDate'] = true; + $desc['hasTime'] = true; + break; + case 'date' : + $desc['hasDate'] = true; + $desc['hasTime'] = false; + break; + case 'time' : + $desc['hasDate'] = false; + $desc['hasTime'] = true; + break; + } + } + else + { + Error( "Can't parse database type '".$row['Type']."' found for field '".$row['Field']."' in table '".$table."'" ); + } + + if ( $asString ) + $columns[$row['Field']] = $desc; + else + $columns[] = $desc; + } + return( $columns ); +} + +function dbFetchMonitor( $mid ) +{ + return( dbFetchOne( "select * from Monitors where Id = '".dbEscape($mid)."'" ) ); +} + +function dbFetchGroup( $gid ) +{ + return( dbFetchOne( "select * from Groups where Id = '".dbEscape($gid)."'" ) ); +} + +?> diff --git a/web/includes/functions.php b/web/includes/functions.php new file mode 100644 index 000000000..17fa04105 --- /dev/null +++ b/web/includes/functions.php @@ -0,0 +1,2436 @@ +/dev/null' ) ) ); +} + +function outputVideoStream( $id, $src, $width, $height, $format, $title="" ) +{ + if ( file_exists( $src ) ) + $mimeType = getMimeType( $src ); + else + { + switch( $format ) + { + case 'asf' : + $mimeType = "video/x-ms-asf"; + break; + case 'avi' : + case 'wmv' : + $mimeType = "video/x-msvideo"; + break; + case 'mov' : + $mimeType = "video/quicktime"; + break; + case 'mpg' : + case 'mpeg' : + $mimeType = "video/mpeg"; + break; + case 'swf' : + $mimeType = "application/x-shockwave-flash"; + break; + case '3gp' : + $mimeType = "video/3gpp"; + break; + default : + $mimeType = "video/$format"; + break; + } + } + if ( !$mimeType || ($mimeType == 'application/octet-stream') ) + $mimeType = 'video/'.$format; + $objectTag = false; + if ( ZM_WEB_USE_OBJECT_TAGS ) + { + switch( $mimeType ) + { + case "video/x-ms-asf" : + case "video/x-msvideo" : + case "video/mp4" : + { + if ( isWindows() ) + { +?> + + + + + + + + + + + + + + + + + + + + + + + +src="" +name="" +width="" +height="" +autostart="1" +autoplay="1" +showcontrols="0" +controller="0"> + + + + + + + + + + + + + + + + <?= ZM_WEB_TITLE_PREFIX ?> - <?= validHtmlStr($title) ?> + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/skins/classic/includes/init.php b/web/skins/classic/includes/init.php new file mode 100644 index 000000000..e69de29bb diff --git a/web/skins/classic/includes/timeline_functions.php b/web/skins/classic/includes/timeline_functions.php new file mode 100644 index 000000000..74a58c06c --- /dev/null +++ b/web/skins/classic/includes/timeline_functions.php @@ -0,0 +1,524 @@ +"; + if ( $scaleRange >= $minLines ) + { + $scale['range'] = $scaleRange; + break; + } + } + if ( !isset($scale['range']) ) + { + $scale['range'] = (int)($range/($scale['factor']*$align)); + } + $scale['divisor'] = 1; + while ( ($scale['range']/$scale['divisor']) > $maxLines ) + { + $scale['divisor']++; + } + $scale['lines'] = (int)($scale['range']/$scale['divisor']); + return( $scale ); +} + +function getYScale( $range, $minLines, $maxLines ) +{ + $scale['range'] = $range; + $scale['divisor'] = 1; + while ( $scale['range']/$scale['divisor'] > $maxLines ) + { + $scale['divisor']++; + } + $scale['lines'] = (int)(($scale['range']-1)/$scale['divisor'])+1; + + return( $scale ); +} + +function getSlotFrame( $slot ) +{ + $slotFrame = isset($slot['frame'])?$slot['frame']['FrameId']:1; + if ( false && $slotFrame ) + { + $slotFrame -= $monitor['PreEventCount']; + if ( $slotFrame < 1 ) + $slotFrame = 1; + } + return( $slotFrame ); +} + +function parseFilterToTree( $filter ) +{ + if ( count($filter['terms']) > 0 ) + { + $postfixExpr = array(); + $postfixStack = array(); + + $priorities = array( + '<' => 1, + '<=' => 1, + '>' => 1, + '>=' => 1, + '=' => 2, + '!=' => 2, + '=~' => 2, + '!~' => 2, + '=[]' => 2, + '![]' => 2, + 'and' => 3, + 'or' => 4, + ); + + for ( $i = 0; $i <= count($filter['terms']); $i++ ) + { + if ( !empty($filter['terms'][$i]['cnj']) ) + { + while( true ) + { + if ( !count($postfixStack) ) + { + $postfixStack[] = array( 'type'=>"cnj", 'value'=>$filter['terms'][$i]['cnj'], 'sqlValue'=>$filter['terms'][$i]['cnj']); + break; + } + elseif ( $postfixStack[count($postfixStack)-1]['type'] == 'obr' ) + { + $postfixStack[] = array( 'type'=>"cnj", 'value'=>$filter['terms'][$i]['cnj'], 'sqlValue'=>$filter['terms'][$i]['cnj']); + break; + } + elseif ( $priorities[$filter['terms'][$i]['cnj']] < $priorities[$postfixStack[count($postfixStack)-1]['value']] ) + { + $postfixStack[] = array( 'type'=>"cnj", 'value'=>$filter['terms'][$i]['cnj'], 'sqlValue'=>$filter['terms'][$i]['cnj']); + break; + } + else + { + $postfixExpr[] = array_pop( $postfixStack ); + } + } + } + if ( !empty($filter['terms'][$i]['obr']) ) + { + for ( $j = 0; $j < $filter['terms'][$i]['obr']; $j++ ) + { + $postfixStack[] = array( 'type'=>"obr", 'value'=>$filter['terms'][$i]['obr']); + } + } + if ( !empty($filter['terms'][$i]['attr']) ) + { + $dtAttr = false; + switch ( $filter['terms'][$i]['attr']) + { + case 'MonitorName': + $sqlValue = 'M.'.preg_replace( '/^Monitor/', '', $filter['terms'][$i]['attr']); + break; + case 'Name': + $sqlValue = "E.Name"; + break; + case 'Cause': + $sqlValue = "E.Cause"; + break; + case 'DateTime': + $sqlValue = "E.StartTime"; + $dtAttr = true; + break; + case 'Date': + $sqlValue = "to_days( E.StartTime )"; + $dtAttr = true; + break; + case 'Time': + $sqlValue = "extract( hour_second from E.StartTime )"; + break; + case 'Weekday': + $sqlValue = "weekday( E.StartTime )"; + break; + case 'Id': + case 'Name': + case 'MonitorId': + case 'Length': + case 'Frames': + case 'AlarmFrames': + case 'TotScore': + case 'AvgScore': + case 'MaxScore': + case 'Archived': + $sqlValue = "E.".$filter['terms'][$i]['attr']; + break; + case 'DiskPercent': + $sqlValue = getDiskPercent(); + break; + case 'DiskBlocks': + $sqlValue = getDiskBlocks(); + break; + default : + $sqlValue = $filter['terms'][$i]['attr']; + break; + } + if ( $dtAttr ) + { + $postfixExpr[] = array( 'type'=>"attr", 'value'=>$filter['terms'][$i]['attr'], 'sqlValue'=>$sqlValue, 'dtAttr'=>true ); + } + else + { + $postfixExpr[] = array( 'type'=>"attr", 'value'=>$filter['terms'][$i]['attr'], 'sqlValue'=>$sqlValue ); + } + } + if ( isset($filter['terms'][$i]['op']) ) + { + if ( empty($filter['terms'][$i]['op']) ) + { + $filter['terms'][$i]['op' ]= '='; + } + switch ( $filter['terms'][$i]['op' ]) + { + case '=' : + case '!=' : + case '>=' : + case '>' : + case '<' : + case '<=' : + $sqlValue = $filter['terms'][$i]['op']; + break; + case '=~' : + $sqlValue = "regexp"; + break; + case '!~' : + $sqlValue = "not regexp"; + break; + case '=[]' : + $sqlValue = 'in ('; + break; + case '![]' : + $sqlValue = 'not in ('; + break; + } + while( true ) + { + if ( !count($postfixStack) ) + { + $postfixStack[] = array( 'type'=>"op", 'value'=>$filter['terms'][$i]['op'], 'sqlValue'=>$sqlValue ); + break; + } + elseif ( $postfixStack[count($postfixStack)-1]['type'] == 'obr' ) + { + $postfixStack[] = array( 'type'=>"op", 'value'=>$filter['terms'][$i]['op'], 'sqlValue'=>$sqlValue ); + break; + } + elseif ( $priorities[$filter['terms'][$i]['op']] < $priorities[$postfixStack[count($postfixStack)-1]['value']] ) + { + $postfixStack[] = array( 'type'=>"op", 'value'=>$filter['terms'][$i]['op'], 'sqlValue'=>$sqlValue ); + break; + } + else + { + $postfixExpr[] = array_pop( $postfixStack ); + } + } + } + if ( isset($filter['terms'][$i]['val']) ) + { + $valueList = array(); + foreach ( preg_split( '/["\'\s]*?,["\'\s]*?/', preg_replace( '/^["\']+?(.+)["\']+?$/', '$1', $filter['terms'][$i]['val' ]) ) as $value ) + { + switch ( $filter['terms'][$i]['attr']) + { + case 'MonitorName': + case 'Name': + case 'Cause': + $value = "'$value'"; + break; + case 'DateTime': + $value = "'".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."'"; + break; + case 'Date': + $value = "to_days( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; + break; + case 'Time': + $value = "extract( hour_second from '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; + break; + case 'Weekday': + $value = "weekday( '".strftime( STRF_FMT_DATETIME_DB, strtotime( $value ) )."' )"; + break; + } + $valueList[] = $value; + } + $postfixExpr[] = array( 'type'=>"val", 'value'=>$filter['terms'][$i]['val'], 'sqlValue'=>join( ',', $valueList ) ); + } + if ( !empty($filter['terms'][$i]['cbr']) ) + { + for ( $j = 0; $j < $filter['terms'][$i]['cbr']; $j++ ) + { + while ( count($postfixStack) ) + { + $element = array_pop( $postfixStack ); + if ( $element['type'] == "obr" ) + { + $postfixExpr[count($postfixExpr)-1]['bracket'] = true; + break; + } + $postfixExpr[] = $element; + } + } + } + } + while ( count($postfixStack) ) + { + $postfixExpr[] = array_pop( $postfixStack ); + } + + $exprStack = array(); + //foreach ( $postfixExpr as $element ) + //{ + //echo $element['value']." "; + //} + //echo "
"; + foreach ( $postfixExpr as $element ) + { + if ( $element['type'] == 'attr' || $element['type'] == 'val' ) + { + $node = array( 'data'=>$element, 'count'=>0 ); + $exprStack[] = $node; + } + elseif ( $element['type'] == 'op' || $element['type'] == 'cnj' ) + { + $right = array_pop( $exprStack ); + $left = array_pop( $exprStack ); + $node = array( 'data'=>$element, 'count'=>2+$left['count']+$right['count'], 'right'=>$right, 'left'=>$left ); + $exprStack[] = $node; + } + else + { + Fatal( "Unexpected element type '".$element['type']."', value '".$element['value']."'" ); + } + } + if ( count($exprStack) != 1 ) + { + Fatal( "Expression stack has ".count($exprStack)." elements" ); + } + $exprTree = array_pop( $exprStack ); + return( $exprTree ); + } + return( false ); +} + +function _parseTreeToInfix( $node ) +{ + $expression = ''; + if ( isset($node) ) + { + if ( isset($node['left']) ) + { + if ( !empty($node['data']['bracket']) ) + $expression .= '( '; + $expression .= _parseTreeToInfix( $node['left'] ); + } + $expression .= $node['data']['value']." "; + if ( isset($node['right']) ) + { + $expression .= _parseTreeToInfix( $node['right'] ); + if ( !empty($node['data']['bracket']) ) + $expression .= ') '; + } + } + return( $expression ); +} + +function parseTreeToInfix( $tree ) +{ + return( _parseTreeToInfix( $tree ) ); +} + +function _parseTreeToSQL( $node, $cbr=false ) +{ + $expression = ''; + if ( $node ) + { + if ( isset($node['left']) ) + { + if ( !empty($node['data']['bracket']) ) + $expression .= '( '; + $expression .= _parseTreeToSQL( $node['left'] ); + } + $inExpr = $node['data']['type'] == 'op' && ($node['data']['value'] == '=[]' || $node['data']['value'] == '![]'); + $expression .= $node['data']['sqlValue']; + if ( !$inExpr ) + $expression .= ' '; + if ( $cbr ) + $expression .= ') '; + if ( isset($node['right']) ) + { + $expression .= _parseTreeToSQL( $node['right'], $inExpr ); + if ( !empty($node['data']['bracket']) ) + $expression .= ') '; + } + } + return( $expression ); +} + +function parseTreeToSQL( $tree ) +{ + return( _parseTreeToSQL( $tree ) ); +} + +function _parseTreeToFilter( $node, &$terms, &$level ) +{ + $elements = array(); + if ( $node ) + { + if ( isset($node['left']) ) + { + if ( !empty($node['data']['bracket']) ) + $terms[$level]['obr'] = 1; + _parseTreeToFilter( $node['left'], $terms, $level ); + } + if ( $node['data']['type'] == 'cnj' ) + { + $level++; + } + $terms[$level][$node['data']['type']] = $node['data']['value']; + if ( isset($node['right']) ) + { + _parseTreeToFilter( $node['right'], $terms, $level ); + if ( !empty($node['data']['bracket']) ) + $terms[$level]['cbr'] = 1; + } + } +} + +function parseTreeToFilter( $tree ) +{ + $terms = array(); + if ( isset($tree) ) + { + $level = 0; + _parseTreeToFilter( $tree, $terms, $level ); + } + return( array( 'terms' => $terms ) ); +} + +function parseTreeToQuery( $tree ) +{ + $filter = parseTreeToFilter( $tree ); + parseFilter( $filter, false, '&' ); + return( $filter['query'] ); +} + +function _drawTree( $node, $level ) +{ + if ( isset($node['left']) ) + { + _drawTree( $node['left'], $level+1 ); + } + echo str_repeat( ".", $level*2 ).$node['data']['value']."
"; + if ( isset($node['right']) ) + { + _drawTree( $node['right'], $level+1 ); + } +} + +function drawTree( $tree ) +{ + _drawTree( $tree, 0 ); +} + +function _extractDatetimeRange( &$node, &$minTime, &$maxTime, &$expandable, $subOr ) +{ + $pruned = $leftPruned = $rightPruned = false; + if ( $node ) + { + if ( isset($node['left']) && isset($node['right']) ) + { + if ( $node['data']['type'] == 'cnj' && $node['data']['value'] == 'or' ) + { + $subOr = true; + } + elseif ( !empty($node['left']['data']['dtAttr']) ) + { + if ( $subOr ) + { + $expandable = false; + } + elseif ( $node['data']['type'] == 'op' ) + { + if ( $node['data']['value'] == '>' || $node['data']['value'] == '>=' ) + { + if ( !$minTime || $minTime > $node['right']['data']['sqlValue'] ) + { + $minTime = $node['right']['data']['value']; + return( true ); + } + } + if ( $node['data']['value'] == '<' || $node['data']['value'] == '<=' ) + { + if ( !$maxTime || $maxTime < $node['right']['data']['sqlValue'] ) + { + $maxTime = $node['right']['data']['value']; + return( true ); + } + } + } + else + { + Fatal( "Unexpected node type '".$node['data']['type']."'" ); + } + return( false ); + } + + $leftPruned = _extractDatetimeRange( $node['left'], $minTime, $maxTime, $expandable, $subOr ); + $rightPruned = _extractDatetimeRange( $node['right'], $minTime, $maxTime, $expandable, $subOr ); + + if ( $leftPruned && $rightPruned ) + { + $pruned = true; + } + elseif ( $leftPruned ) + { + $node = $node['right']; + } + elseif ( $rightPruned ) + { + $node = $node['left']; + } + } + } + return( $pruned ); +} + +function extractDatetimeRange( &$tree, &$minTime, &$maxTime, &$expandable ) +{ + $minTime = ""; + $maxTime = ""; + $expandable = true; + + _extractDateTimeRange( $tree, $minTime, $maxTime, $expandable, false ); +} + +function appendDatetimeRange( &$tree, $minTime, $maxTime=false ) +{ + $attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'DateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 ); + $valNode = array( 'data'=>array( 'type'=>'val', 'value'=>$minTime, 'sqlValue'=>$minTime ), 'count'=>0 ); + $opNode = array( 'data'=>array( 'type'=>'op', 'value'=>'>=', 'sqlValue'=>'>=' ), 'count'=>2, 'left'=>$attrNode, 'right'=>$valNode ); + if ( isset($tree) ) + { + $cnjNode = array( 'data'=>array( 'type'=>'cnj', 'value'=>'and', 'sqlValue'=>'and' ), 'count'=>2+$tree['count']+$opNode['count'], 'left'=>$tree, 'right'=>$opNode ); + $tree = $cnjNode; + } + else + { + $tree = $opNode; + } + + if ( $maxTime ) + { + $attrNode = array( 'data'=>array( 'type'=>'attr', 'value'=>'DateTime', 'sqlValue'=>'E.StartTime', 'dtAttr'=>true ), 'count'=>0 ); + $valNode = array( 'data'=>array( 'type'=>'val', 'value'=>$maxTime, 'sqlValue'=>$maxTime ), 'count'=>0 ); + $opNode = array( 'data'=>array( 'type'=>'op', 'value'=>'<=', 'sqlValue'=>'<=' ), 'count'=>2, 'left'=>$attrNode, 'right'=>$valNode ); + $cnjNode = array( 'data'=>array( 'type'=>'cnj', 'value'=>'and', 'sqlValue'=>'and' ), 'count'=>2+$tree['count']+$opNode['count'], 'left'=>$tree, 'right'=>$opNode ); + $tree = $cnjNode; + } +} + +?> diff --git a/web/skins/classic/js/Makefile.am b/web/skins/classic/js/Makefile.am new file mode 100644 index 000000000..22f944d9e --- /dev/null +++ b/web/skins/classic/js/Makefile.am @@ -0,0 +1,7 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/classic/js + +dist_web_DATA = \ + skin.js \ + skin.js.php diff --git a/web/skins/classic/js/Makefile.in b/web/skins/classic/js/Makefile.in new file mode 100644 index 000000000..04d248260 --- /dev/null +++ b/web/skins/classic/js/Makefile.in @@ -0,0 +1,454 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/classic/js +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/classic/js +dist_web_DATA = \ + skin.js \ + skin.js.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/classic/js/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/classic/js/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/classic/js/skin.js b/web/skins/classic/js/skin.js new file mode 100644 index 000000000..32d83a9cd --- /dev/null +++ b/web/skins/classic/js/skin.js @@ -0,0 +1,289 @@ +// +// ZoneMinder base static javascript file, $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 file should only contain static JavaScript and no php. +// Use skin.js.php for JavaScript that need pre-processing +// + +// Javascript window sizes +var popupSizes = { + 'bandwidth': { 'width': 200, 'height': 120 }, + 'console': { 'width': 750, 'height': 312 }, + 'control': { 'width': 380, 'height': 480 }, + 'controlcaps': { 'width': 780, 'height': 320 }, + 'controlcap': { 'width': 400, 'height': 400 }, + 'cycle': { 'addWidth': 16, 'minWidth': 384, 'addHeight': 48 }, + 'device': { 'width': 260, 'height': 150 }, + 'devices': { 'width': 400, 'height': 240 }, + 'donate': { 'width': 500, 'height': 280 }, + 'event': { 'addWidth': 108, 'minWidth': 496, 'addHeight': 200, minHeight: 540 }, + 'eventdetail': { 'width': 400, 'height': 220 }, + 'events': { 'width': 760, 'height': 480 }, + 'export': { 'width': 400, 'height': 340 }, + 'filter': { 'width': 720, 'height': 360 }, + 'filtersave': { 'width': 560, 'height': 120 }, + 'frame': { 'addWidth': 32, 'minWidth': 384, 'addHeight': 100 }, + 'frames': { 'width': 500, 'height': 300 }, + 'function': { 'width': 248, 'height': 92 }, + 'group': { 'width': 360, 'height': 180 }, + 'groups': { 'width': 400, 'height': 220 }, + 'image': { 'addWidth': 48, 'addHeight': 80 }, + 'log': { 'width': 980, 'height': 720 }, + 'login': { 'width': 720, 'height': 480 }, + 'logout': { 'width': 240, 'height': 100 }, + 'monitor': { 'width': 380, 'height': 364 }, + 'monitorpreset':{ 'width': 400, 'height': 200 }, + 'monitorprobe': { 'width': 500, 'height': 240 }, + 'monitorselect':{ 'width': 160, 'height': 200 }, + 'montage': { 'width': -1, 'height': -1 }, + 'optionhelp': { 'width': 400, 'height': 320 }, + 'options': { 'width': 960, 'height': 620 }, + 'preset': { 'width': 300, 'height': 120 }, + 'settings': { 'width': 200, 'height': 225 }, + 'state': { 'width': 240, 'height': 124 }, + 'stats': { 'width': 740, 'height': 200 }, + 'timeline': { 'width': 760, 'height': 540 }, + 'user': { 'width': 320, 'height': 420 }, + 'version': { 'width': 360, 'height': 140 }, + 'video': { 'width': 420, 'height': 360 }, + 'videoview': { 'addWidth': 48, 'addHeight': 80 }, + 'watch': { 'addWidth': 96, 'minWidth': 420, 'addHeight': 384 }, + 'zone': { 'addWidth': 450, 'addHeight': 200, 'minHeight': 450 }, + 'zones': { 'addWidth': 72, 'addHeight': 232 } +}; + +var popupOptions = "resizable,scrollbars,status=no"; + +// Deprecated +function newWindow( url, name, width, height ) +{ + var windowId = window.open( url, name, popupOptions+",width="+width+",height="+height ); +} + +function getPopupSize( tag, width, height ) +{ + var popupSize = Object.clone( popupSizes[tag] ); + if ( !popupSize ) + { + Error( "Can't find window size for tag '"+tag+"'" ); + return( { 'width': 0, 'height': 0 } ); + } + if ( popupSize.width && popupSize.height ) + { + if ( width || height ) + Warning( "Ignoring passed dimensions "+width+"x"+height+" when getting popup size for tag '"+tag+"'" ); + return( popupSize ); + } + if ( popupSize.addWidth ) + { + popupSize.width = popupSize.addWidth; + if ( !width ) + Error( "Got addWidth but no passed width when getting popup size for tag '"+tag+"'" ); + else + popupSize.width += parseInt(width); + } + else if ( width ) + { + popupSize.width = width; + Error( "Got passed width but no addWidth when getting popup size for tag '"+tag+"'" ); + } + if ( popupSize.minWidth && popupSize.width < popupSize.minWidth ) + { + Warning( "Adjusting to minimum width when getting popup size for tag '"+tag+"'" ); + popupSize.width = popupSize.minWidth; + } + if ( popupSize.addHeight ) + { + popupSize.height = popupSize.addHeight; + if ( !height ) + Error( "Got addHeight but no passed height when getting popup size for tag '"+tag+"'" ); + else + popupSize.height += parseInt(height); + } + else if ( height ) + { + popupSize.height = height; + Error( "Got passed height but no addHeight when getting popup size for tag '"+tag+"'" ); + } + if ( popupSize.minHeight && popupSize.height < popupSize.minHeight ) + { + Warning( "Adjusting to minimum height when getting popup size for tag '"+tag+"'" ); + popupSize.height = popupSize.minHeight; + } + Debug( popupSize ); + return( popupSize ); +} + +function zmWindow() +{ + var zmWin = window.open( 'http://www.zoneminder.com', 'ZoneMinder' ); + zmWin.focus(); +} + +function createPopup( url, name, tag, width, height ) +{ + var popupSize = getPopupSize( tag, width, height ); + var popupDimensions = ""; + if ( popupSize.width > 0 ) + popupDimensions += ",width="+popupSize.width; + if ( popupSize.height > 0 ) + popupDimensions += ",height="+popupSize.height; + var popup = window.open( url, name, popupOptions+popupDimensions ); +} + +function createEventPopup( eventId, eventFilter, width, height ) +{ + var url = '?view=event&eid='+eventId; + if ( eventFilter ) + url += eventFilter; + var name = 'zmEvent'; + var popupSize = getPopupSize( 'event', width, height ); + var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); +} + +function createFramesPopup( eventId, width, height ) +{ + var url = '?view=frames&eid='+eventId; + var name = 'zmFrames'; + var popupSize = getPopupSize( 'frames', width, height ); + var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); +} + +function createFramePopup( eventId, frameId, width, height ) +{ + var url = '?view=frame&eid='+eventId+'&fid='+frameId; + var name = 'zmFrame'; + var popupSize = getPopupSize( 'frame', width, height ); + var popup = window.open( url, name, popupOptions+",width="+popupSize.width+",height="+popupSize.height ); +} + +function windowToFront() +{ + top.window.focus(); +} + +function closeWindow() +{ + top.window.close(); +} + +function refreshWindow() +{ + window.location.reload( true ); +} + +function refreshParentWindow() +{ + if ( window.opener ) + window.opener.location.reload( true ); +} + +//Shows a message if there is an error in the streamObj or the stream doesn't exist. Returns true if error, false otherwise. +function checkStreamForErrors( funcName, streamObj ) +{ + if ( !streamObj ) + { + Error( funcName+": stream object was null" ); + return true; + } + if ( streamObj.result == "Error" ) + { + Error( funcName+" stream error: "+streamObj.message ); + return true; + } + return false; +} + +function secsToTime( seconds ) +{ + var timeString = "--"; + if ( seconds < 60 ) + timeString = seconds.toString(); + else if ( seconds < 60*60 ) + { + var timeMins = parseInt(seconds/60); + var timeSecs = seconds%60; + if ( timeSecs < 10 ) + timeSecs = '0'+timeSecs.toString().substr( 0, 4 ); + else + timeSecs = timeSecs.toString().substr( 0, 5 ); + timeString = timeMins+":"+timeSecs; + } + else + { + var timeHours = parseInt(seconds/3600); + var timeMins = (seconds%3600)/60; + var timeSecs = seconds%60; + if ( timeMins < 10 ) + timeMins = '0'+timeMins.toString().substr( 0, 4 ); + else + timeMins = timeMins.toString().substr( 0, 5 ); + if ( timeSecs < 10 ) + timeSecs = '0'+timeSecs.toString().substr( 0, 4 ); + else + timeSecs = timeSecs.toString().substr( 0, 5 ); + timeString = timeHours+":"+timeMins+":"+timeSecs; + } + return( timeString ); +} + +function submitTab( tab ) +{ + var form = $('contentForm'); + form.action.value = ""; + form.tab.value = tab; + form.submit(); +} + +function configureDeleteButton( element ) +{ + var form = element.form; + var checked = element.checked; + if ( !checked ) + { + for ( var i = 0; i < form.elements.length; i++ ) + { + if ( form.elements[i].name == element.name ) + { + if ( form.elements[i].checked ) + { + checked = true; + break; + } + } + } + } + form.deleteBtn.disabled = !checked; +} + +function confirmDelete( message ) +{ + return( confirm( message?message:'Are you sure you wish to delete?' ) ); +} + +if ( refreshParent ) +{ + refreshParentWindow(); +} + +if ( focusWindow ) +{ + windowToFront(); +} diff --git a/web/skins/classic/js/skin.js.php b/web/skins/classic/js/skin.js.php new file mode 100644 index 000000000..16b8f055e --- /dev/null +++ b/web/skins/classic/js/skin.js.php @@ -0,0 +1,40 @@ + +var AJAX_TIMEOUT = ; + +var currentView = ''; +var thisUrl = ""; +var skinPath = ""; + +var canEditSystem = ; +var canViewSystem = ; + +var refreshParent = ; + +var focusWindow = ; + +var imagePrefix = ""; diff --git a/web/skins/classic/lang/Makefile.am b/web/skins/classic/lang/Makefile.am new file mode 100644 index 000000000..6a089b4fa --- /dev/null +++ b/web/skins/classic/lang/Makefile.am @@ -0,0 +1,5 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/classic/lang + +dist_web_DATA = # No files here diff --git a/web/skins/classic/lang/Makefile.in b/web/skins/classic/lang/Makefile.in new file mode 100644 index 000000000..1349ff476 --- /dev/null +++ b/web/skins/classic/lang/Makefile.in @@ -0,0 +1,451 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/classic/lang +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/classic/lang +dist_web_DATA = # No files here +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/classic/lang/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/classic/lang/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/classic/skin.php b/web/skins/classic/skin.php new file mode 100644 index 000000000..9e0aea10f --- /dev/null +++ b/web/skins/classic/skin.php @@ -0,0 +1,73 @@ + diff --git a/web/skins/classic/svn-commit.tmp b/web/skins/classic/svn-commit.tmp new file mode 100644 index 000000000..a8bae9fc0 --- /dev/null +++ b/web/skins/classic/svn-commit.tmp @@ -0,0 +1,5 @@ + +--This line, and those below, will be ignored-- + +M views/plugin.php +M views/css/plugin.css diff --git a/web/skins/classic/views/Makefile.am b/web/skins/classic/views/Makefile.am new file mode 100644 index 000000000..58c72b78f --- /dev/null +++ b/web/skins/classic/views/Makefile.am @@ -0,0 +1,55 @@ +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = \ + css \ + js + +webdir = @WEB_PREFIX@/skins/classic/views + +dist_web_DATA = \ + bandwidth.php \ + blank.php \ + console.php \ + controlcap.php \ + controlcaps.php \ + control.php \ + controlpreset.php \ + cycle.php \ + device.php \ + devices.php \ + donate.php \ + error.php \ + eventdetail.php \ + event.php \ + events.php \ + export.php \ + filter.php \ + filtersave.php \ + frame.php \ + frames.php \ + function.php \ + group.php \ + groups.php \ + log.php \ + login.php \ + logout.php \ + Makefile.am \ + monitor.php \ + monitorpreset.php \ + monitorprobe.php \ + montage.php \ + none.php \ + optionhelp.php \ + options.php \ + postlogin.php \ + settings.php \ + state.php \ + stats.php \ + status.php \ + timeline.php \ + user.php \ + version.php \ + video.php \ + watch.php \ + zone.php \ + zones.php diff --git a/web/skins/classic/views/Makefile.in b/web/skins/classic/views/Makefile.in new file mode 100644 index 000000000..13da5f23f --- /dev/null +++ b/web/skins/classic/views/Makefile.in @@ -0,0 +1,701 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/classic/views +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = \ + css \ + js + +webdir = @WEB_PREFIX@/skins/classic/views +dist_web_DATA = \ + bandwidth.php \ + blank.php \ + console.php \ + controlcap.php \ + controlcaps.php \ + control.php \ + controlpreset.php \ + cycle.php \ + device.php \ + devices.php \ + donate.php \ + error.php \ + eventdetail.php \ + event.php \ + events.php \ + export.php \ + filter.php \ + filtersave.php \ + frame.php \ + frames.php \ + function.php \ + group.php \ + groups.php \ + log.php \ + login.php \ + logout.php \ + Makefile.am \ + monitor.php \ + monitorpreset.php \ + monitorprobe.php \ + montage.php \ + none.php \ + optionhelp.php \ + options.php \ + postlogin.php \ + settings.php \ + state.php \ + stats.php \ + status.php \ + timeline.php \ + user.php \ + version.php \ + video.php \ + watch.php \ + zone.php \ + zones.php + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/classic/views/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/classic/views/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dist_webDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/classic/views/bandwidth.php b/web/skins/classic/views/bandwidth.php new file mode 100644 index 000000000..5c09ed446 --- /dev/null +++ b/web/skins/classic/views/bandwidth.php @@ -0,0 +1,58 @@ + + +
+ +
+
+ + +

+

+
+ +
+
+
+
+ + diff --git a/web/skins/classic/views/blank.php b/web/skins/classic/views/blank.php new file mode 100644 index 000000000..ac5c9caa7 --- /dev/null +++ b/web/skins/classic/views/blank.php @@ -0,0 +1,37 @@ + + + + + + + + + diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php new file mode 100644 index 000000000..bc00e4da4 --- /dev/null +++ b/web/skins/classic/views/console.php @@ -0,0 +1,342 @@ + $SLANG['Events'], + "filter" => array( + "terms" => array( + ) + ), + ), + array( + "title" => $SLANG['Hour'], + "filter" => array( + "terms" => array( + array( "attr" => "DateTime", "op" => ">=", "val" => "-1 hour" ), + ) + ), + ), + array( + "title" => $SLANG['Day'], + "filter" => array( + "terms" => array( + array( "attr" => "DateTime", "op" => ">=", "val" => "-1 day" ), + ) + ), + ), + array( + "title" => $SLANG['Week'], + "filter" => array( + "terms" => array( + array( "attr" => "DateTime", "op" => ">=", "val" => "-7 day" ), + ) + ), + ), + array( + "title" => $SLANG['Month'], + "filter" => array( + "terms" => array( + array( "attr" => "DateTime", "op" => ">=", "val" => "-1 month" ), + ) + ), + ), + array( + "title" => $SLANG['Archived'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "1" ), + ) + ), + ), +); + +$running = daemonCheck(); +$status = $running?$SLANG['Running']:$SLANG['Stopped']; + +if ( $group = dbFetchOne( "select * from Groups where Id = '".(empty($_COOKIE['zmGroup'])?0:dbEscape($_COOKIE['zmGroup']))."'" ) ) + $groupIds = array_flip(explode( ',', $group['MonitorIds'] )); + +noCacheHeaders(); + +$maxWidth = 0; +$maxHeight = 0; +$cycleCount = 0; +$minSequence = 0; +$maxSequence = 1; +$seqIdList = array(); +$monitors = dbFetchAll( "select * from Monitors order by Sequence asc" ); +$displayMonitors = array(); +for ( $i = 0; $i < count($monitors); $i++ ) +{ + if ( !visibleMonitor( $monitors[$i]['Id'] ) ) + { + continue; + } + if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) ) + { + continue; + } + $monitors[$i]['Show'] = true; + if ( empty($minSequence) || ($monitors[$i]['Sequence'] < $minSequence) ) + { + $minSequence = $monitors[$i]['Sequence']; + } + if ( $monitors[$i]['Sequence'] > $maxSequence ) + { + $maxSequence = $monitors[$i]['Sequence']; + } + $monitors[$i]['zmc'] = zmcStatus( $monitors[$i] ); + $monitors[$i]['zma'] = zmaStatus( $monitors[$i] ); + $monitors[$i]['ZoneCount'] = dbFetchOne( "select count(Id) as ZoneCount from Zones where MonitorId = '".$monitors[$i]['Id']."'", "ZoneCount" ); + $counts = array(); + for ( $j = 0; $j < count($eventCounts); $j++ ) + { + $filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( "cnj" => "and", "attr" => "MonitorId", "op" => "=", "val" => $monitors[$i]['Id'] ) ); + parseFilter( $filter ); + $counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j"; + $monitors[$i]['eventCounts'][$j]['filter'] = $filter; + } + $sql = "select ".join($counts,", ")." from Events as E where MonitorId = '".$monitors[$i]['Id']."'"; + $counts = dbFetchOne( $sql ); + if ( $monitors[$i]['Function'] != 'None' ) + { + $cycleCount++; + $scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); + $scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); + if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth; + if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight; + } + $monitors[$i] = array_merge( $monitors[$i], $counts ); + $seqIdList[] = $monitors[$i]['Id']; + $displayMonitors[] = $monitors[$i]; +} +$lastId = 0; +$seqIdUpList = array(); +foreach ( $seqIdList as $seqId ) +{ + if ( !empty($lastId) ) + $seqIdUpList[$seqId] = $lastId; + else + $seqIdUpList[$seqId] = $seqId; + $lastId = $seqId; +} +$lastId = 0; +$seqIdDownList = array(); +foreach ( array_reverse($seqIdList) as $seqId ) +{ + if ( !empty($lastId) ) + $seqIdDownList[$seqId] = $lastId; + else + $seqIdDownList[$seqId] = $seqId; + $lastId = $seqId; +} + +$cycleWidth = $maxWidth; +$cycleHeight = $maxHeight; + +$eventsView = ZM_WEB_EVENTS_VIEW; +$eventsWindow = 'zm'.ucfirst(ZM_WEB_EVENTS_VIEW); + +$eventCount = 0; +for ( $i = 0; $i < count($eventCounts); $i++ ) +{ + $eventCounts[$i]['total'] = 0; +} +$zoneCount = 0; +foreach( $displayMonitors as $monitor ) +{ + for ( $i = 0; $i < count($eventCounts); $i++ ) + { + $eventCounts[$i]['total'] += $monitor['EventCount'.$i]; + } + $zoneCount += $monitor['ZoneCount']; +} + +$seqUpFile = getSkinFile( 'graphics/seq-u.gif' ); +$seqDownFile = getSkinFile( 'graphics/seq-d.gif' ); + +$versionClass = (ZM_DYN_DB_VERSION&&(ZM_DYN_DB_VERSION!=ZM_VERSION))?'errorText':''; + +xhtmlHeaders( __FILE__, $SLANG['Console'] ); +?> + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
'.$monitor['Function'].'', canEdit( 'Monitors' ) ) ?>'.$monitor['Device'].' ('.$monitor['Channel'].')', canEdit( 'Monitors' ) ) ?>'.preg_replace( '/^.*@/', '', $monitor['Host'] ).'', canEdit( 'Monitors' ) ) ?>'.preg_replace( '/^.*\//', '', $monitor['Path'] ).'', canEdit( 'Monitors' ) ) ?>'.preg_replace( '/^.*\//', '', $monitor['Path'] ).'', canEdit( 'Monitors' ) ) ?> ', $monitor['Sequence']>$minSequence ) ?>', $monitor['Sequence']<$maxSequence ) ?> disabled="disabled"/>
+
+
+
+ + diff --git a/web/skins/classic/views/control.php b/web/skins/classic/views/control.php new file mode 100644 index 000000000..df3b33adc --- /dev/null +++ b/web/skins/classic/views/control.php @@ -0,0 +1,81 @@ + + +
+ +
+
+ +
+
+
+ + diff --git a/web/skins/classic/views/controlcap.php b/web/skins/classic/views/controlcap.php new file mode 100644 index 000000000..7fbc61f61 --- /dev/null +++ b/web/skins/classic/views/controlcap.php @@ -0,0 +1,512 @@ + $SLANG['New'], + 'Type' => "Local", + 'Protocol' => "", + 'CanWake' => "", + 'CanSleep' => "", + 'CanReset' => "", + 'CanMove' => "", + 'CanMoveDiag' => "", + 'CanMoveMap' => "", + 'CanMoveAbs' => "", + 'CanMoveRel' => "", + 'CanMoveCon' => "", + 'CanPan' => "", + 'MinPanRange' => "", + 'MaxPanRange' => "", + 'MinPanStep' => "", + 'MaxPanStep' => "", + 'HasPanSpeed' => "", + 'MinPanSpeed' => "", + 'MaxPanSpeed' => "", + 'HasTurboPan' => "", + 'TurboPanSpeed' => "", + 'CanTilt' => "", + 'MinTiltRange' => "", + 'MaxTiltRange' => "", + 'MinTiltStep' => "", + 'MaxTiltStep' => "", + 'HasTiltSpeed' => "", + 'MinTiltSpeed' => "", + 'MaxTiltSpeed' => "", + 'HasTurboTilt' => "", + 'TurboTiltSpeed' => "", + 'CanZoom' => "", + 'CanZoomAbs' => "", + 'CanZoomRel' => "", + 'CanZoomCon' => "", + 'MinZoomRange' => "", + 'MaxZoomRange' => "", + 'MinZoomStep' => "", + 'MaxZoomStep' => "", + 'HasZoomSpeed' => "", + 'MinZoomSpeed' => "", + 'MaxZoomSpeed' => "", + 'CanFocus' => "", + 'CanAutoFocus' => "", + 'CanFocusAbs' => "", + 'CanFocusRel' => "", + 'CanFocusCon' => "", + 'MinFocusRange' => "", + 'MaxFocusRange' => "", + 'MinFocusStep' => "", + 'MaxFocusStep' => "", + 'HasFocusSpeed' => "", + 'MinFocusSpeed' => "", + 'MaxFocusSpeed' => "", + 'CanIris' => "", + 'CanAutoIris' => "", + 'CanIrisAbs' => "", + 'CanIrisRel' => "", + 'CanIrisCon' => "", + 'MinIrisRange' => "", + 'MaxIrisRange' => "", + 'MinIrisStep' => "", + 'MaxIrisStep' => "", + 'HasIrisSpeed' => "", + 'MinIrisSpeed' => "", + 'MaxIrisSpeed' => "", + 'CanGain' => "", + 'CanAutoGain' => "", + 'CanGainAbs' => "", + 'CanGainRel' => "", + 'CanGainCon' => "", + 'MinGainRange' => "", + 'MaxGainRange' => "", + 'MinGainStep' => "", + 'MaxGainStep' => "", + 'HasGainSpeed' => "", + 'MinGainSpeed' => "", + 'MaxGainSpeed' => "", + 'CanWhite' => "", + 'CanAutoWhite' => "", + 'CanWhiteAbs' => "", + 'CanWhiteRel' => "", + 'CanWhiteCon' => "", + 'MinWhiteRange' => "", + 'MaxWhiteRange' => "", + 'MinWhiteStep' => "", + 'MaxWhiteStep' => "", + 'HasWhiteSpeed' => "", + 'MinWhiteSpeed' => "", + 'MaxWhiteSpeed' => "", + 'HasPresets' => "", + 'NumPresets' => "", + 'HasHomePreset' => "", + 'CanSetPresets' => "", + ); + } + $newControl = $control; +} + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['ControlCap']." - ".$newControl['Name'] ); +?> + +
+ +
+
    +$value ) +{ + if ( $tab == $name ) + { +?> +
  • + +
  • + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +$SLANG['Local'], 'Remote'=>$SLANG['Remote'] ); +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked">
checked="checked"/>
checked="checked"/>
checked="checked">
checked="checked"/>
checked="checked"/>
checked="checked">
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked">
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
checked="checked"/>
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/controlcaps.php b/web/skins/classic/views/controlcaps.php new file mode 100644 index 000000000..0a737a3f5 --- /dev/null +++ b/web/skins/classic/views/controlcaps.php @@ -0,0 +1,90 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
disabled="disabled"/>
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/controlpreset.php b/web/skins/classic/views/controlpreset.php new file mode 100644 index 000000000..45ffc4dd9 --- /dev/null +++ b/web/skins/classic/views/controlpreset.php @@ -0,0 +1,72 @@ + + +
+ +
+
+ + + + + +

+

+
+ +
+
+
+
+ + diff --git a/web/skins/classic/views/css/Makefile.am b/web/skins/classic/views/css/Makefile.am new file mode 100644 index 000000000..39c270cf7 --- /dev/null +++ b/web/skins/classic/views/css/Makefile.am @@ -0,0 +1,31 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/classic/views/css + +dist_web_DATA = \ + console.css \ + controlcaps.css \ + control.css \ + devices.css \ + event.css \ + events.css \ + export.css \ + filter.css \ + frame.css \ + frames.css \ + groups.css \ + log.css \ + monitor.css \ + montage_2wide.css \ + montage_3wide50enlarge.css \ + montage_3wide.css \ + montage_4wide.css \ + montage.css \ + montage_freeform.css \ + options.css \ + stats.css \ + timeline.css \ + timeline.css.php \ + video.css \ + watch.css \ + zone.css diff --git a/web/skins/classic/views/css/Makefile.in b/web/skins/classic/views/css/Makefile.in new file mode 100644 index 000000000..6b852e415 --- /dev/null +++ b/web/skins/classic/views/css/Makefile.in @@ -0,0 +1,478 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/classic/views/css +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/classic/views/css +dist_web_DATA = \ + console.css \ + controlcaps.css \ + control.css \ + devices.css \ + event.css \ + events.css \ + export.css \ + filter.css \ + frame.css \ + frames.css \ + groups.css \ + log.css \ + monitor.css \ + montage_2wide.css \ + montage_3wide50enlarge.css \ + montage_3wide.css \ + montage_4wide.css \ + montage.css \ + montage_freeform.css \ + options.css \ + stats.css \ + timeline.css \ + timeline.css.php \ + video.css \ + watch.css \ + zone.css + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/classic/views/css/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/classic/views/css/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/classic/views/css/console.css b/web/skins/classic/views/css/console.css new file mode 100644 index 000000000..49920402a --- /dev/null +++ b/web/skins/classic/views/css/console.css @@ -0,0 +1,97 @@ +#systemTime { + float: left; +} + +#title { + margin: 0 auto; + text-align: center; + width: 50%; +} + +#systemStats { + float: right; +} + +#monitorSummary { + float: left; + text-align: left; + width: 20%; +} + +#devices { + float: left; +} + +#loginBandwidth { + margin: 0 auto; + text-align: center; + width: 40%; +} + +#cycleMontage { + float: right; +} + +#options { + float: right; + text-align: right; + width: 20%; +} + +#consoleTable { + width: 100%; +} + +#consoleTable tr.highlight { + background-color: #eeeeee; +} + +#consoleTable thead th { + padding-bottom: 4px; + vertical-align: middle; +} + +#consoleTable tfoot td { + padding-top: 4px; + vertical-align: middle; +} + +#consoleTable th,td { + height: 16px; + text-align: left; +} + +#consoleTable .colOrder { + text-align: center; +} + +#consoleTable .colMark { + width: 32px; + text-align: center; +} + +#consoleTable .colEvents { + text-align: right; +} + +#consoleTable .colZones { + text-align: right; +} + +#consoleTable .colLeftButtons { + text-align: left; +} + +#consoleTable .colLeftButtons input { + margin-right: 24px; +} + +#consoleTable .colRightButtons { + text-align: right; + padding-right: 8px; +} + +#consoleTable .colRightButtons input { + margin: 0 8px; +} + diff --git a/web/skins/classic/views/css/control.css b/web/skins/classic/views/css/control.css new file mode 100644 index 000000000..0096ffcd7 --- /dev/null +++ b/web/skins/classic/views/css/control.css @@ -0,0 +1 @@ +@import url(../../css/control.css); diff --git a/web/skins/classic/views/css/controlcaps.css b/web/skins/classic/views/css/controlcaps.css new file mode 100644 index 000000000..1a2783fd7 --- /dev/null +++ b/web/skins/classic/views/css/controlcaps.css @@ -0,0 +1,3 @@ +#content table.major .colCanMove, #content table.major .colCanZoom, #content table.major .colCanFocus, #content table.major .colCanIris, #content table.major .colCanWhiteBal, #content table.major .colHasPresets { + text-align: center; +} diff --git a/web/skins/classic/views/css/devices.css b/web/skins/classic/views/css/devices.css new file mode 100644 index 000000000..6015985d0 --- /dev/null +++ b/web/skins/classic/views/css/devices.css @@ -0,0 +1,4 @@ +input.set { + border: 1px #7F7FB2 dashed; +} + diff --git a/web/skins/classic/views/css/event.css b/web/skins/classic/views/css/event.css new file mode 100644 index 000000000..995a06c1d --- /dev/null +++ b/web/skins/classic/views/css/event.css @@ -0,0 +1,232 @@ +#dataBar { + width: 100%; + margin: 2px auto; + text-align: center; +} + +#dataBar #dataTable { + width: 100%; +} + +#dataBar #dataTable td { + text-align: center; + padding: 2px; +} + +#menuBar1 { + width: 100%; + height: 1.5em; + padding: 3px 0; + text-align: center; + clear: both; +} + +#menuBar1 #nameControl { + float: left; +} + +#menuBar1 #nameControl #eventName { + margin-right: 4px; +} + +#menuBar1 #replayControl { + float: right; + margin-left: 8px; +} + +#menuBar1 #scaleControl { + float: right; + margin-left: 8px; +} + +#menuBar2 { + width: 100%; + height: 1.2em; + padding: 3px 0; + margin-bottom: 4px; +} + +#menuBar2 div { + text-align: left; + float: left; + padding: 0 12px; +} + +#menuBar2 #closeWindow { + float: right; + text-align: right; +} + +#imageFeed { + text-align: center; +} + +#monitorStatus { + width: 100%; + margin-top: 3px; + margin-bottom: 2px; + text-align: center; +} + +#monitorStatus #enableAlarms { + position: absolute; + left: 4px; +} + +#monitorStatus #forceAlarm { + position: absolute; + right: 4px; +} + +#monitorStatus #monitorState { +} + +#dvrControls { + margin-top: 3px; + margin-bottom: 2px; + text-align: center; +} + +#dvrControls input { + height: 20px; + width: 28px; + padding-bottom: 3px; + margin: 0 3px; +} + +#dvrControls input[disabled=disabled] { + color: #aaaaaa; +} + +#dvrControls input.active { + border: 1px solid blue; +} + +#dvrControls input.inactive { + border: 1px solid green; +} + +#dvrControls input.unavail { + border: 1px solid red; +} + +#replayStatus { + margin: 3px 0 2px; + text-align: center; + clear: both; +} + +#replayStatus > span { + padding: 0 4px; +} + +#progressBar { + position: relative; + border: 1px solid #666666; + height: 15px; + margin: 0 auto; +} + +#progressBar .progressBox { + position: absolute; + top: 0px; + left: 0px; + height: 15px; + background: #eeeeee; + border-left: 1px solid #999999; +} + +#progressBar .complete { + background: #aaaaaa; +} + +#eventStills { + width: 100%; + position: relative; +} + +#eventThumbsPanel { + position: relative; + width: 100%; + margin: 4px auto; + z-index: 1; +} + +#eventThumbs { + margin: 0 auto; + width: 100%; + overflow: hidden; + height: 300px; +} + +#eventThumbs img { + height: 25px; /* HACK - Although this is pixels it will be interpreted as a scale %ge, so 25px = 25% scaling for thumbnails */ + margin: 2px; + background-color: #dddddd; +} + +#eventThumbs img.placeholder { + /* width: 100px; */ +} + +#eventThumbs img.selected { +} + +#eventImagePanel { + position: absolute; + z-index: 10; +} + +#eventImageFrame { + border: 2px solid gray; + background-color: white; + padding: 4px; +} + +#eventImage { +} + +#eventImageBar { + margin-top: 2px; +} + +#eventImageStats { + float: left; +} + +#eventImageData { + margin: 0 auto; + padding-top: 2px; +} + +#eventImageClose { + float: right; +} + +#eventImageNav { + position: relative; +} + +#eventImageNav input { + width: 32px; + font-size: 16px; +} + +#thumbsSliderPanel { + width: 400px; + margin: 4px auto 0; + background: #888888; + padding: 1px; +} + +#thumbsSlider { + width: 400px; + height: 10px; + background: #dddddd; +} + +#thumbsKnob { + width: 8px; + height: 10px; + background-color: #444444; +} diff --git a/web/skins/classic/views/css/events.css b/web/skins/classic/views/css/events.css new file mode 100644 index 000000000..5726e904d --- /dev/null +++ b/web/skins/classic/views/css/events.css @@ -0,0 +1,42 @@ +#controls { + height: 16px; + width: 100%; + text-align: center; + margin: 0 auto; + position: relative; +} + +#controls a { + width: 32%; +} + +#controls #refreshLink { + position: absolute; + left: 0%; + text-align: left; +} + +#controls #filterLink { + position: absolute; + left: 34%; + text-align: center; +} + +#controls #timelineLink { + position: absolute; + left: 68%; + text-align: right; +} + +#contentTable.major .colTime { + white-space: nowrap; +} + +#contentTable.major .colId, #contentTable.major .colDuration, #contentTable.major .colFrames, #contentTable.major .colAlarmFrames, #contentTable.major .colTotScore, #contentTable.major .colMaxScore, #contentTable.major .colAvgScore { + text-align: center; +} + +#contentTable.major td.colDuration { + text-align: right; + padding-right: 8px; +} diff --git a/web/skins/classic/views/css/export.css b/web/skins/classic/views/css/export.css new file mode 100644 index 000000000..e22851ca0 --- /dev/null +++ b/web/skins/classic/views/css/export.css @@ -0,0 +1,15 @@ +#contentTable + input { + margin-top: 6px; +} + +#contentTable th, #contentTable td { + white-space: nowrap; +} + +#exportProgress { + margin: 8px auto 4px; +} + +#downloadLink { + margin-top: 8px; +} diff --git a/web/skins/classic/views/css/filter.css b/web/skins/classic/views/css/filter.css new file mode 100644 index 000000000..2287cfea2 --- /dev/null +++ b/web/skins/classic/views/css/filter.css @@ -0,0 +1,25 @@ +#filterSelector { +} + +table.filterTable { + width: 100%; +} + +#fieldsTable td { + height: 16px; +} + +#fieldsTable input[type=button] { + width: 1.6em; + margin-left: 2px; + text-align: center; +} + +#sortTable input[type=text] { + margin-right: 4px; +} + +#actionsTable input[type=text] { + margin-left: 4px; +} + diff --git a/web/skins/classic/views/css/frame.css b/web/skins/classic/views/css/frame.css new file mode 100644 index 000000000..2c7789349 --- /dev/null +++ b/web/skins/classic/views/css/frame.css @@ -0,0 +1,30 @@ +#controls { + width: 80%; + text-align: center; + margin: 0 auto; +} + +#controls a { + width: 40px; + margin-left: -20px; +} + +#firstLink { + position: absolute; + left: 13%; +} + +#prevLink { + position: absolute; + left: 37%; +} + +#nextLink { + position: absolute; + left: 63%; +} + +#lastLink { + position: absolute; + left: 87%; +} diff --git a/web/skins/classic/views/css/frames.css b/web/skins/classic/views/css/frames.css new file mode 100644 index 000000000..249fa3751 --- /dev/null +++ b/web/skins/classic/views/css/frames.css @@ -0,0 +1,15 @@ +#contentTable.major .colId, #contentTable.major .colType, #contentTable.major .colTimeStamp, #contentTable.major .colTimeDelta, #contentTable.major .colScore { + text-align: center; +} + +tr.alarm { + background-color: #fa8072; +} + +tr.bulk { + background-color: #cccccc; +} + +tr.normal { + background-color: #ffffff; +} diff --git a/web/skins/classic/views/css/groups.css b/web/skins/classic/views/css/groups.css new file mode 100644 index 000000000..64f5013de --- /dev/null +++ b/web/skins/classic/views/css/groups.css @@ -0,0 +1,6 @@ +#contentTable .colSelect { + text-align: center; +} + +#contentTable .colSelect input { +} diff --git a/web/skins/classic/views/css/log.css b/web/skins/classic/views/css/log.css new file mode 100644 index 000000000..44f309b9b --- /dev/null +++ b/web/skins/classic/views/css/log.css @@ -0,0 +1,53 @@ +#logSummary { + margin: 4px auto 0; + border-collapse: collapse; +} + +#logSummary tr { + margin: 0; + padding: 0; +} + +#logSummary td { + border: 1px solid #7f7fb2; + padding: 0 6px; + text-align: center; + font-size: 10px; + line-height: 15px; +} + +tr.log-fat td { + background-color:#ffcccc; + font-weight: bold; +} + +tr.log-err td { + background-color:#ffcccc; +} + +tr.log-war td { + background-color: #ffe4b5; +} + +tr.log-dbg td { + color: #666666; + font-style: italic; +} + +#exportLog label { + vertical-align: middle; +} + +#exportLog input[type=radio] { + margin-right: 4px; + vertical-align: middle; +} + +#exportError { + display: none; + color: #dc143c; + margin-bottom: 8px; +} + +#exportErrorText { +} diff --git a/web/skins/classic/views/css/monitor.css b/web/skins/classic/views/css/monitor.css new file mode 100644 index 000000000..7cac28fe1 --- /dev/null +++ b/web/skins/classic/views/css/monitor.css @@ -0,0 +1,5 @@ +.swatch { + border: 1px solid black; + margin-left: 3px; + padding: 0px; +} diff --git a/web/skins/classic/views/css/montage.css b/web/skins/classic/views/css/montage.css new file mode 100644 index 000000000..1afd402a7 --- /dev/null +++ b/web/skins/classic/views/css/montage.css @@ -0,0 +1,41 @@ +#header { + width: 99%; +} + +#layout { + margin-right: 10px; +} + +#content { + width: 99%; +} + +#monitors .alarm { + color: #ff0000; +} + +#monitors .alert { + color: #ffa500; +} + +#monitors .imageFeed { + text-align: center; + vertical-align: middle; +} + +#monitors .imageFeed img.idle { + border: 2px solid #ffffff; +} + +#monitors .imageFeed img.alarm { + border: 2px solid #ff0000; +} + +#monitors .imageFeed img.alert { + border: 2px solid #ffa500; +} + +#monitors .monitorState { + margin: 2px auto; + text-align: center; +} diff --git a/web/skins/classic/views/css/montage_2wide.css b/web/skins/classic/views/css/montage_2wide.css new file mode 100644 index 000000000..b0fa77298 --- /dev/null +++ b/web/skins/classic/views/css/montage_2wide.css @@ -0,0 +1,30 @@ +#monitors { + width: 100%; + margin: 0 auto; + text-align: center; +} + +#monitors .monitorFrame { + padding: 1px; + float: left; +} + +#monitors .monitor { +} + +#monitorFrame0, #monitorFrame2, #monitorFrame4, #monitorFrame6, #monitorFrame8, #monitorFrame10, #monitorFrame12, #monitorFrame14 { + width: 49%; + clear: both; +} + +#monitor0, #monitor2, #monitor4, #monitor6, #monitor8, #monitor10, #monitor12, #monitor14 { + float: right; +} + +#monitorFrame1, #monitorFrame3, #monitorFrame5, #monitorFrame7, #monitorFrame9, #monitorFrame11, #monitorFrame13, #monitorFrame15 { + width: 49%; +} + +#monitor1, #monitor3, #monitor5, #monitor7, #monitor9, #monitor11, #monitor13, #monitor15 { + float: left; +} diff --git a/web/skins/classic/views/css/montage_3wide.css b/web/skins/classic/views/css/montage_3wide.css new file mode 100644 index 000000000..81f0c00ae --- /dev/null +++ b/web/skins/classic/views/css/montage_3wide.css @@ -0,0 +1,37 @@ +#monitors { + width: 100%; + margin: 0 auto; + text-align: center; +} + +#monitors .monitorFrame { + padding: 1px; + float: left; + width: 33%; +} + +#monitors .monitor { + text-align: center; +} + +#monitorFrame0, #monitorFrame3, #monitorFrame6, #monitorFrame9, #monitorFrame12, #monitorFrame15 { + clear: both; +} + +#monitor0, #monitor3, #monitor6, #monitor9, #monitor12, #monitor15 { + float: right; +} + +#monitorFrame1, #monitorFrame4, #monitorFrame7, #monitorFrame10, #monitorFrame13, #monitorFrame16 { + text-align: center; +} + +#monitor1, #monitor4, #monitor7, #monitor10, #monitor13, #monitor16 { +} + +#monitorFrame2, #monitorFrame5, #monitorFrame8, #monitorFrame11, #monitorFrame14, #monitorFrame17 { +} + +#monitor2, #monitor5, #monitor8, #monitor11, #monitor14, #monitor17 { + float: left; +} diff --git a/web/skins/classic/views/css/montage_3wide50enlarge.css b/web/skins/classic/views/css/montage_3wide50enlarge.css new file mode 100644 index 000000000..59bedd9ba --- /dev/null +++ b/web/skins/classic/views/css/montage_3wide50enlarge.css @@ -0,0 +1,74 @@ +#monitors { + width: 100%; + margin: 0 auto; + text-align: center; +} + +#monitors .monitorFrame { + float: left; + padding: 1px; +} + +#monitors .monitor { + text-align: center; +} + +#monitorFrame0, #monitorFrame3, #monitorFrame6, #monitorFrame9, #monitorFrame12, #monitorFrame15 { + width: 32%; + text-align: right; + clear: both; +} + +#monitor0, #monitor3, #monitor6, #monitor9, #monitor12, #monitor15 { + margin-left: auto; + margin-right: 0; +} + +#monitorFrame1, #monitorFrame4, #monitorFrame7, #monitorFrame10, #monitorFrame13, #monitorFrame16 { + width: 32%; + text-align: center; +} + +#monitor1, #monitor4, #monitor7, #monitor10, #monitor13, #monitor16 { + margin-left: auto; + margin-right: auto; +} + +#monitorFrame2, #monitorFrame5, #monitorFrame8, #monitorFrame11, #monitorFrame14, #monitorFrame17 { + width: 32%; + text-align: left; +} + +#monitor2, #monitor5, #monitor8, #monitor11, #monitor14, #monitor17 { + margin-left: 0; + margin-right: auto; +} + +#monitors .imageFeed img { + width: 100%; + height: 100%; +} + +#monitors .monitorFrame > div.alarm, #monitors .monitorFrame > div.alert { + position: absolute; + width: 96%; + left: 2%; + top: 72px; +} + +#monitors .monitorFrame > div.alert { + z-index: 100; +} + +#monitors .monitorFrame > div.alarm { + z-index: 200; +} + +#monitors .monitorFrame div.alarm, #monitors .monitorFrame div.alert { + font-size: 140%; + line-height: 160%; +} + +#monitors .monitorFrame div.monitorState { + text-align: center; +} diff --git a/web/skins/classic/views/css/montage_4wide.css b/web/skins/classic/views/css/montage_4wide.css new file mode 100644 index 000000000..4e5b7bc49 --- /dev/null +++ b/web/skins/classic/views/css/montage_4wide.css @@ -0,0 +1,44 @@ +#monitors { + width: 100%; + margin: 0 auto; + text-align: center; +} + +#monitors .monitorFrame { + padding: 1px; + float: left; + width: 24.5%; +} + +#monitors .monitor { + text-align: center; +} + +#monitorFrame0, #monitorFrame4, #monitorFrame8, #monitorFrame12, #monitorFrame16, #monitorFrame20 { + clear: both; +} + +#monitor0, #monitor4, #monitor8, #monitor12, #monitor16, #monitor20 { + float: right; +} + +#monitorFrame1, #monitorFrame5, #monitorFrame9, #monitorFrame13, #monitorFrame17, #monitorFrame21 { + text-align: center; +} + +#monitor1, #monitor5, #monitor9, #monitor13, #monitor17, #monitor21 { +} + +#monitorFrame2, #monitorFrame6, #monitorFrame10, #monitorFrame14, #monitorFrame18, #monitorFrame22 { + text-align: center; +} + +#monitor2, #monitor6, #monitor10, #monitor14, #monitor18, #monitor22 { +} + +#monitorFrame3, #monitorFrame7, #monitorFrame11, #monitorFrame15, #monitorFrame19, #monitorFrame23 { +} + +#monitor3, #monitor7, #monitor11, #monitor15, #monitor19, #monitor23 { + float: left; +} diff --git a/web/skins/classic/views/css/montage_freeform.css b/web/skins/classic/views/css/montage_freeform.css new file mode 100644 index 000000000..da6a4bb22 --- /dev/null +++ b/web/skins/classic/views/css/montage_freeform.css @@ -0,0 +1,9 @@ +#monitors { + margin: 0 auto; + text-align: center; +} + +#monitors .monitorFrame { + float: left; + padding: 1px; +} diff --git a/web/skins/classic/views/css/options.css b/web/skins/classic/views/css/options.css new file mode 100644 index 000000000..f2635edea --- /dev/null +++ b/web/skins/classic/views/css/options.css @@ -0,0 +1,24 @@ +input.small { + width: 6em; +} + +input.medium { + width: 9em; +} + +input.large { + width: 20em; +} + +#contentTable.optionTable th, #contentTable.optionTable td { + vertical-align: top; +} + +#contentTable.userTable th, #contentTable.userTable td { + text-align: center; +} + +#contentTable.userTable .colMonitor, #contentTable.userTable .colUsername { + text-align: left; +} + diff --git a/web/skins/classic/views/css/plugin.css b/web/skins/classic/views/css/plugin.css new file mode 100644 index 000000000..040e26558 --- /dev/null +++ b/web/skins/classic/views/css/plugin.css @@ -0,0 +1,20 @@ +#settingsPanel { + float: left; + margin: 0 2px; +} + +#pluginSettings { + border-collapse: collapse; +} + +#pluginSettings th, #pluginSettings td { + border: 1px solid #7f7fb2; + padding: 3px; + text-align: left; +} + +#pluginSettings th[scope=row] { + padding: 4px 3px 3px; + vertical-align: top; + white-space: nowrap; +} diff --git a/web/skins/classic/views/css/stats.css b/web/skins/classic/views/css/stats.css new file mode 100644 index 000000000..c47e85e3a --- /dev/null +++ b/web/skins/classic/views/css/stats.css @@ -0,0 +1,9 @@ +#contentTable.major .colZone, #contentTable.major .colPixelDiff, #contentTable.major .colAlarmPx, #contentTable.major .colFilterPx, #contentTable.major .colBlobPx, #contentTable.major .colBlobs, #contentTable.major .colBlobSizes, #contentTable.major .colAlarmLimits, #contentTable.major .colScore { + + text-align: center; +} + +#contentTable.major .rowNoStats { + text-align: center; + padding: 20px; +} diff --git a/web/skins/classic/views/css/timeline.css b/web/skins/classic/views/css/timeline.css new file mode 100644 index 000000000..6b66ea4e1 --- /dev/null +++ b/web/skins/classic/views/css/timeline.css @@ -0,0 +1,222 @@ +#content { + position: relative; + text-align: center; + border: 1px solid #666666; + margin: 0 auto; +} + +#title { + position: relative; + margin: 0 auto; + color: #016A9D; + height: 30px; + font-size: 13px; + font-weight: bold; + line-height: 20px; +} + +#listLink { + position: absolute; + top: 5px; + left: 20px; + height: 15px; +} + +#closeLink { + position: absolute; + top: 5px; + right: 20px; + height: 15px; +} + +#topPanel { + position: relative; + height: 220px; + margin: 4px auto 6px; +} + +#topPanel #imagePanel +{ + width: 50%; + float: left; + text-align: right; +} + +#topPanel #image { + float: right; + margin: 0 auto; + width: 90%; + text-align: right; + margin-right: 2px; + background-color: #eeeeee; + border: 1px solid #c8c8c8; +} + +#topPanel #image img { + float: left; + top: 0px; + background-color: #f8f8f8; + width: 100%; +} + +#topPanel #dataPanel { + width: 45%; + float: left; + text-align: left; + margin-left: 2px; +} + +#topPanel #textPanel { + text-align: left; + width: 100%; + height: 140px; + margin: 0 auto; + color: #016A9D; + font-size: 11px; + font-weight: bold; + line-height: 14px; + background-color: #eeeeee; + border: 1px solid #c8c8c8; + padding: 2px; +} + +#topPanel #navPanel { + width: 100%; + height: 70px; + margin: 4px auto; +} + +#topPanel #navPanel input { + background-color: #eeeeee; + border: 1px solid #c8c8c8; + padding: 5px; +} + +#chartPanel { + position: relative; + margin: 0 auto; +} + +#chartPanel #chart { + position: relative; + border: 1px solid black; + margin: 0 auto; + z-index: 0; +} + +#chartPanel #activity { + position: absolute; + text-align: center; + left: 0px; + border-bottom: 1px solid #cccccc; +} + +#chartPanel #activity div.activity { + position: absolute; + bottom: 0px; + z-index: 3; + width: 1px; +} + +#chartPanel .events { + position: absolute; + text-align: center; + left: 0px; + background-color: #fcfcfc; + border-bottom: 1px solid black; +} + +#chartPanel .event { + position: absolute; + bottom: 0px; + z-index: 3; +} + +#chartLabels { + margin: 25px auto 0; + text-align: center; +} + +#range { + width: 30%; + margin: 0 auto; + color: #016A9D; + font-size: 11px; + font-weight: bold; + line-height: 20px; +} + +#key { + float: right; + margin-top: -4px; + text-align: right; +} + +span.keyEntry { +} + +img.keyBox { + position: relative; + border: 1px solid black; + width: 16px; + height: 16px; + top: 4px; + margin-left: 4px; +} + +div.majGridX { + position: absolute; + z-index: 1; + top: 0px; + width: 1px; + border-left: dotted 1px #cccccc; +} + +div.majTickX { + position: absolute; + bottom: -7px; + width: 1px; + height: 7px; + border-left: solid 1px black; +} + +div.majLabelX { + position: absolute; + text-align: center; + bottom: -20px; + width: 50px; + font-size: 9px; + font-weight: normal; +} + +div.majGridY { + position: absolute; + z-index: 1; + left: 0px; + height: 1px; + border-top: dotted 1px #cccccc; +} + +div.majTickY { + position: absolute; + left: -7px; + height: 1px; + width: 7px; + border-top: solid 1px black; +} + +div.majLabelY { + position: absolute; + text-align: right; + left: -30px; + width: 20px; + font-size: 9px; + font-weight: normal; +} + +div.zoom { + position: absolute; + z-index: 2; + bottom: 0px; +} + diff --git a/web/skins/classic/views/css/timeline.css.php b/web/skins/classic/views/css/timeline.css.php new file mode 100644 index 000000000..3bc75fbcf --- /dev/null +++ b/web/skins/classic/views/css/timeline.css.php @@ -0,0 +1,77 @@ +.chartSize { + width: px; + height: px; +} + +.graphSize { + width: px; + height: px; +} + +.graphHeight { + height: px; +} + +.graphWidth { + width: px; +} + +.imageSize { + width: px; + height: px; +} + +.imageHeight { + height: px; +} + +.activitySize { + width: px; + height: px; +} + +.eventsSize { + width: px; + height: px; +} + +.eventsHeight { + height: px; +} + +#chartPanel .eventsPos { + top: px; +} + +#chartPanel .activityPos { + top: px; +} + +#chartPanel .eventsPos { + top: px; +} + +.monitorColour { + background-color: ; +} + diff --git a/web/skins/classic/views/css/video.css b/web/skins/classic/views/css/video.css new file mode 100644 index 000000000..7e9708f2c --- /dev/null +++ b/web/skins/classic/views/css/video.css @@ -0,0 +1,19 @@ +#contentTable + input { + margin-top: 6px; +} + +#videoProgress { + margin: 8px auto 4px; +} + +#videoFilesHeader { + margin: 8px auto 4px; +} + +#videoNoFiles { + margin: 4px auto; +} + +#videoFile { + margin-bottom: 6px; +} diff --git a/web/skins/classic/views/css/watch.css b/web/skins/classic/views/css/watch.css new file mode 100644 index 000000000..82cfca234 --- /dev/null +++ b/web/skins/classic/views/css/watch.css @@ -0,0 +1,134 @@ +@import url(../../css/control.css); + +#menuBar { + margin: 6px auto 4px; + text-align: center; +} + +#menuBar #monitorName { + float: left; +} + +#menuBar #closeControl { + float: right; +} + +#menuBar #menuControls { + margin: 0 auto; + width: 60%; +} + +#menuBar #menuControls #controlControl { + float: left; +} + +#menuBar #menuControls #eventsControl { + float: left; +} + +#menuBar #menuControls #settingsControl { + float: right; +} + +#menuBar #menuControls #scaleControl { + margin: 0 auto; +} + +#imageFeed{ + text-align: center; +} + +#monitorStatus { + margin: 4px auto; + text-align: center; +} + +#monitorStatus #enableDisableAlarms { + float: left; +} + +#monitorStatus #forceCancelAlarm { + float: right; +} + +#monitorStatus #monitorState { +} + +#dvrControls { + margin-top: 3px; + margin-bottom: 2px; + text-align: center; +} + +#dvrControls input { + height: 20px; + width: 28px; + padding-bottom: 3px; + margin: 0 3px; +} + +#dvrControls input[disabled] { + color: #aaaaaa; +} + +#dvrControls input.active { + border: 1px solid blue; +} + +#dvrControls input.inactive { + border: 1px solid green; +} + +#dvrControls input.unavail { + border: 1px solid red; +} + +#replayStatus { + margin: 3px 0 2px; + text-align: center; + clear: both; +} + +#replayStatus > span { + padding: 0 4px; +} + +#events { + margin: 0 auto; +} + +#eventList { + width: 100%; +} + +#eventList thead td { + font-weight: bold; +} + +#eventList th, #eventList td { + text-align: center; +} + +li { + display: inline; + list-style-type: none; +} + +span.alarm { + color: #DC143C; + font-weight: bold; +} + +span.alert { + color: #FF8C00; + font-weight: bold; +} + +#eventList tr.recent { + background-color: #B0E0E6; +} + +#eventList tr.highlight { + background-color: #DCDCDC; +} + diff --git a/web/skins/classic/views/css/zone.css b/web/skins/classic/views/css/zone.css new file mode 100644 index 000000000..554255a74 --- /dev/null +++ b/web/skins/classic/views/css/zone.css @@ -0,0 +1,91 @@ +#settingsPanel { + float: left; + margin: 0 2px; +} + +#zoneSettings { + border-collapse: collapse; +} + +#zoneSettings th, #zoneSettings td { + border: 1px solid #7f7fb2; + padding: 3px; + text-align: left; +} + +#zoneSettings th[scope=row] { + padding: 4px 3px 3px; + vertical-align: top; + white-space: nowrap; +} + +#definitionPanel { + float: left; + margin: 0 2px; + text-align: center; +} + +#definitionPanel input[type=submit], #definitionPanel input[type=submit] { + margin: 0 4px; +} + +#imagePanel { + position: relative; +} + +#imageFrame { + position: relative; + padding: 0 6px 6px 0; /* Double margin of points below */ +} + +#imageFrame div { + position: absolute; + width: 7px; + height: 7px; + margin-left: -3px; + margin-top: -3px; + z-index: 5; +} + +#imageFrame div { + background-image: url(../../graphics/point-g.gif); +} + +#imageFrame div.highlight { + background-image: url(../../graphics/point-o.gif); +} + +#imageFrame div.active { + background-image: url(../../graphics/point-r.gif); +} + +#zonePoints { + margin: 8px 0; + border-collapse: collapse; +} + +#zonePoints td { + vertical-align: top; +} + +#zonePoints table { + border-collapse: collapse; +} + +#zonePoints table tr.highlight { + background-color: #f0e68c; +} + +#zonePoints table tr.active { + background-color: #ffa07a; +} + +#zonePoints table th, #zonePoints table td { + border: 1px solid #7f7fb2; + padding: 3px; + text-align: center; +} + +#zonePoints table a { + margin: 0 2px; +} diff --git a/web/skins/classic/views/cycle.php b/web/skins/classic/views/cycle.php new file mode 100644 index 000000000..258d21af5 --- /dev/null +++ b/web/skins/classic/views/cycle.php @@ -0,0 +1,129 @@ + + +
+ +
+
+ +
+
+
+ + diff --git a/web/skins/classic/views/device.php b/web/skins/classic/views/device.php new file mode 100644 index 000000000..645c14295 --- /dev/null +++ b/web/skins/classic/views/device.php @@ -0,0 +1,71 @@ + "", + "Name" => "New Device", + "KeyString" => "" + ); +} + +xhtmlHeaders( __FILE__, $SLANG['Device']." - ".$newDevice['Name'] ); +?> + +
+ +
+
+ + + + + + + + + + + + + + +
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/devices.php b/web/skins/classic/views/devices.php new file mode 100644 index 000000000..106f3d4a8 --- /dev/null +++ b/web/skins/classic/views/devices.php @@ -0,0 +1,86 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + +
'.validHtmlStr($device['Name']).' ('.validHtmlStr($device['KeyString']).')', canEdit( 'Devices' ) ) ?> onclick="switchDeviceOn( this, '' )"/> onclick="switchDeviceOff( this, '' )"/> disabled="disabled"/>
+
+ /> + + +
+
+
+
+ + diff --git a/web/skins/classic/views/donate.php b/web/skins/classic/views/donate.php new file mode 100644 index 000000000..34ee4efa3 --- /dev/null +++ b/web/skins/classic/views/donate.php @@ -0,0 +1,65 @@ + $SLANG['DonateYes'], + "hour" => $SLANG['DonateRemindHour'], + "day" => $SLANG['DonateRemindDay'], + "week" => $SLANG['DonateRemindWeek'], + "month" => $SLANG['DonateRemindMonth'], + "never" => $SLANG['DonateRemindNever'], + "already" => $SLANG['DonateAlready'], +); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Donate'] ); +?> + +
+ +
+
+ + +

+ +

+

+ +

+
+ + +
+
+
+
+ + diff --git a/web/skins/classic/views/error.php b/web/skins/classic/views/error.php new file mode 100644 index 000000000..c18ae307e --- /dev/null +++ b/web/skins/classic/views/error.php @@ -0,0 +1,43 @@ + + +
+ +
+

+ +

+

+ +

+

+ +

+
+
+ + diff --git a/web/skins/classic/views/event.php b/web/skins/classic/views/event.php new file mode 100644 index 000000000..5ac1e1740 --- /dev/null +++ b/web/skins/classic/views/event.php @@ -0,0 +1,222 @@ + $SLANG['ReplaySingle'], + 'all' => $SLANG['ReplayAll'], + 'gapless' => $SLANG['ReplayGapless'], +); + +if ( isset( $_REQUEST['streamMode'] ) ) + $streamMode = validHtmlStr($_REQUEST['streamMode']); +else + $streamMode = canStream()?'stream':'stills'; + +if ( isset( $_REQUEST['replayMode'] ) ) + $replayMode = validHtmlStr($_REQUEST['replayMode']); +if ( isset( $_COOKIE['replayMode']) && preg_match('#^[a-z]+$#', $_COOKIE['replayMode']) ) + $replayMode = validHtmlStr($_COOKIE['replayMode']); + else + $replayMode = array_shift( array_keys( $replayModes ) ); + +parseSort(); +parseFilter( $_REQUEST['filter'] ); +$filterQuery = $_REQUEST['filter']['query']; + +$panelSections = 40; +$panelSectionWidth = (int)ceil(reScale($event['Width'],$scale)/$panelSections); +$panelWidth = ($panelSections*$panelSectionWidth-1); + +$connkey = generateConnKey(); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Event'] ); +?> + +
+
+
+ + + + + + + + + +
s">/">//
+
+ + +
+
+ +
+

+ + + + + + + + + +

+
+ Mode:   + Rate: x + Progress: s + Zoom: x +
+ +
+ +
+
+ + diff --git a/web/skins/classic/views/eventdetail.php b/web/skins/classic/views/eventdetail.php new file mode 100644 index 000000000..437b95f98 --- /dev/null +++ b/web/skins/classic/views/eventdetail.php @@ -0,0 +1,134 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/events.php b/web/skins/classic/views/events.php new file mode 100644 index 000000000..5959bdc6f --- /dev/null +++ b/web/skins/classic/views/events.php @@ -0,0 +1,270 @@ + $limit ) +{ + $nEvents = $limit; +} +$pages = (int)ceil($nEvents/ZM_WEB_EVENTS_PER_PAGE); +if ( $pages > 1 ) +{ + if ( !empty($page) ) + { + if ( $page < 0 ) + $page = 1; + if ( $page > $pages ) + $page = $pages; + } +} +if ( !empty($page) ) +{ + $limitStart = (($page-1)*ZM_WEB_EVENTS_PER_PAGE); + if ( empty( $limit ) ) + { + $limitAmount = ZM_WEB_EVENTS_PER_PAGE; + } + else + { + $limitLeft = $limit - $limitStart; + $limitAmount = ($limitLeft>ZM_WEB_EVENTS_PER_PAGE)?ZM_WEB_EVENTS_PER_PAGE:$limitLeft; + } + $eventsSql .= " limit $limitStart, $limitAmount"; +} +elseif ( !empty( $limit ) ) +{ + $eventsSql .= " limit 0, ".dbEscape($limit); +} + +$maxWidth = 0; +$maxHeight = 0; +$archived = false; +$unarchived = false; +$events = array(); +foreach ( dbFetchAll( $eventsSql ) as $event ) +{ + $events[] = $event; + $scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); + $eventWidth = reScale( $event['Width'], $scale ); + $eventHeight = reScale( $event['Height'], $scale ); + if ( $maxWidth < $eventWidth ) $maxWidth = $eventWidth; + if ( $maxHeight < $eventHeight ) $maxHeight = $eventHeight; + if ( $event['Archived'] ) + $archived = true; + else + $unarchived = true; +} + +$maxShortcuts = 5; +$pagination = getPagination( $pages, $page, $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$limit ); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Events'] ); + +?> + +
+ +
+
+ + + + + + + + +

+ +

+ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
disabled="disabled"/>
' ) ?>  disabled="disabled"/>
+ +

+ +
+ + + + + + +
+ +
+
+
+ + diff --git a/web/skins/classic/views/export.php b/web/skins/classic/views/export.php new file mode 100644 index 000000000..5ca464f88 --- /dev/null +++ b/web/skins/classic/views/export.php @@ -0,0 +1,131 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
checked="checked" onclick="configureExportButton( this )"/>
checked="checked" onclick="configureExportButton( this )"/>
checked="checked" onclick="configureExportButton( this )"/>
checked="checked" onclick="configureExportButton( this )"/>
checked="checked" onclick="configureExportButton( this )"/>
+ checked="checked" onclick="configureExportButton( this )"/> + checked="checked" onclick="configureExportButton( this )"/> +
+ +
+
+ +

+ + + + + +
+ + diff --git a/web/skins/classic/views/filter.php b/web/skins/classic/views/filter.php new file mode 100644 index 000000000..21b804353 --- /dev/null +++ b/web/skins/classic/views/filter.php @@ -0,0 +1,331 @@ +$SLANG['ChooseFilter'] ); +foreach ( dbFetchAll( "select * from Filters order by Name" ) as $row ) +{ + $filterNames[$row['Name']] = $row['Name']; + if ( $row['Background'] ) + $filterNames[$row['Name']] .= "*"; + if ( !empty($_REQUEST['reload']) && isset($_REQUEST['filterName']) && $_REQUEST['filterName'] == $row['Name'] ) + $dbFilter = $row; +} + +$backgroundStr = ""; +if ( isset($dbFilter) ) +{ + if ( $dbFilter['Background'] ) + $backgroundStr = '['.strtolower($SLANG['Background']).']'; + $_REQUEST['filter'] = jsonDecode( $dbFilter['Query'] ); + $_REQUEST['sort_field'] = isset($_REQUEST['filter']['sort_field'])?$_REQUEST['filter']['sort_field']:"DateTime"; + $_REQUEST['sort_asc'] = isset($_REQUEST['filter']['sort_asc'])?$_REQUEST['filter']['sort_asc']:"1"; + $_REQUEST['limit'] = isset($_REQUEST['filter']['limit'])?$_REQUEST['filter']['limit']:""; + unset( $_REQUEST['filter']['sort_field'] ); + unset( $_REQUEST['filter']['sort_asc'] ); + unset( $_REQUEST['filter']['limit'] ); +} + +$conjunctionTypes = array( + 'and' => $SLANG['ConjAnd'], + 'or' => $SLANG['ConjOr'] +); +$obracketTypes = array(); +$cbracketTypes = array(); +if ( isset($_REQUEST['filter']['terms']) ) +{ + for ( $i = 0; $i <= count($_REQUEST['filter']['terms'])-2; $i++ ) + { + $obracketTypes[$i] = str_repeat( "(", $i ); + $cbracketTypes[$i] = str_repeat( ")", $i ); + } +} + +$attrTypes = array( + 'MonitorId' => $SLANG['AttrMonitorId'], + 'MonitorName' => $SLANG['AttrMonitorName'], + 'Id' => $SLANG['AttrId'], + 'Name' => $SLANG['AttrName'], + 'Cause' => $SLANG['AttrCause'], + 'Notes' => $SLANG['AttrNotes'], + 'DateTime' => $SLANG['AttrDateTime'], + 'Date' => $SLANG['AttrDate'], + 'Time' => $SLANG['AttrTime'], + 'Weekday' => $SLANG['AttrWeekday'], + 'Length' => $SLANG['AttrDuration'], + 'Frames' => $SLANG['AttrFrames'], + 'AlarmFrames' => $SLANG['AttrAlarmFrames'], + 'TotScore' => $SLANG['AttrTotalScore'], + 'AvgScore' => $SLANG['AttrAvgScore'], + 'MaxScore' => $SLANG['AttrMaxScore'], + 'Archived' => $SLANG['AttrArchiveStatus'], + 'DiskPercent' => $SLANG['AttrDiskPercent'], + 'DiskBlocks' => $SLANG['AttrDiskBlocks'], + 'SystemLoad' => $SLANG['AttrSystemLoad'], +); +$opTypes = array( + '=' => $SLANG['OpEq'], + '!=' => $SLANG['OpNe'], + '>=' => $SLANG['OpGtEq'], + '>' => $SLANG['OpGt'], + '<' => $SLANG['OpLt'], + '<=' => $SLANG['OpLtEq'], + '=~' => $SLANG['OpMatches'], + '!~' => $SLANG['OpNotMatches'], + '=[]' => $SLANG['OpIn'], + '![]' => $SLANG['OpNotIn'], +); +$archiveTypes = array( + '0' => $SLANG['ArchUnarchived'], + '1' => $SLANG['ArchArchived'] +); +$weekdays = array(); +for ( $i = 0; $i < 7; $i++ ) +{ + $weekdays[$i] = strftime( "%A", mktime( 12, 0, 0, 1, $i+1, 2001 ) ); +} +$sort_fields = array( + 'Id' => $SLANG['AttrId'], + 'Name' => $SLANG['AttrName'], + 'Cause' => $SLANG['AttrCause'], + 'Notes' => $SLANG['AttrNotes'], + 'MonitorName' => $SLANG['AttrMonitorName'], + 'DateTime' => $SLANG['AttrDateTime'], + 'Length' => $SLANG['AttrDuration'], + 'Frames' => $SLANG['AttrFrames'], + 'AlarmFrames' => $SLANG['AttrAlarmFrames'], + 'TotScore' => $SLANG['AttrTotalScore'], + 'AvgScore' => $SLANG['AttrAvgScore'], + 'MaxScore' => $SLANG['AttrMaxScore'], +); +$sort_dirns = array( + '1' => $SLANG['SortAsc'], + '0' => $SLANG['SortDesc'] +); +if ( empty($_REQUEST['sort_field']) ) +{ + $_REQUEST['sort_field'] = ZM_WEB_EVENT_SORT_FIELD; + $_REQUEST['sort_asc'] = (ZM_WEB_EVENT_SORT_ORDER == "asc"); +} + +$hasCal = file_exists( 'tools/jscalendar/calendar.js' ); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['EventFilter'] ); +?> + +
+ +
+
+ + + + + + + + +
+
1 ) { echo buildSelect( $selectName, $filterNames, "submitToFilter( this, 1 );" ); } else { ?>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
  2 ) { echo buildSelect( "filter[terms][$i][obr]", $obracketTypes ); } else { ?>  2 ) { echo buildSelect( "filter[terms][$i][cbr]", $cbracketTypes ); } else { ?>  1 ) { ?>
+
+ + + + + + + +
"/>
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
checked="checked" onclick="updateButtons( this )"/>
checked="checked" onclick="updateButtons( this )"/>
checked="checked" onclick="updateButtons( this )"/>
checked="checked" onclick="updateButtons( this )"/>
checked="checked" onclick="updateButtons( this )"/>
checked="checked"/>" size="32" maxlength="255" onchange="updateButtons( this )"/>
checked="checked" onclick="updateButtons( this )"/>
+
+
+ + + + + + + +
+
+
+
+ + diff --git a/web/skins/classic/views/filtersave.php b/web/skins/classic/views/filtersave.php new file mode 100644 index 000000000..ba040d72f --- /dev/null +++ b/web/skins/classic/views/filtersave.php @@ -0,0 +1,86 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + +

+ +

+ +

+ +

+ +

+ checked="checked"/> +

+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/frame.php b/web/skins/classic/views/frame.php new file mode 100644 index 000000000..1cbe3634e --- /dev/null +++ b/web/skins/classic/views/frame.php @@ -0,0 +1,103 @@ +$fid, 'Type'=>'Normal', 'Score'=>0 ); +} +else +{ + $frame = dbFetchOne( "select * from Frames where EventId = '".dbEscape($eid)."' and Score = '".$event['MaxScore']."'" ); +} + +$maxFid = $event['Frames']; + +$firstFid = 1; +$prevFid = $frame['FrameId']-1; +$nextFid = $frame['FrameId']+1; +$lastFid = $maxFid; + +$alarmFrame = $frame['Type']=='Alarm'; + +if ( isset( $_REQUEST['scale'] ) ) + $scale = validInt($_REQUEST['scale']); +else + $scale = max( reScale( SCALE_BASE, $event['DefaultScale'], ZM_WEB_DEFAULT_SCALE ), SCALE_BASE ); + +$imageData = getImageSrc( $event, $frame, $scale, (isset($_REQUEST['show']) && $_REQUEST['show']=="capt") ); + +$imagePath = $imageData['thumbPath']; +$eventPath = $imageData['eventPath']; +$dImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-d.jpg", $eventPath, $frame['FrameId'] ); +$rImagePath = sprintf( "%s/%0".ZM_EVENT_IMAGE_DIGITS."d-diag-r.jpg", $eventPath, $frame['FrameId'] ); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Frame']." - ".$event['Id']." - ".$frame['FrameId'] ); +?> + +
+ +
+

"><?= $frame['EventId']." class=""/>

+

+ 1 ) { ?> + + 1 ) { ?> + + + + + + +

+ +

+

" width="" height="" class=""/>

+ +

+

+ +
+
+ + diff --git a/web/skins/classic/views/frames.php b/web/skins/classic/views/frames.php new file mode 100644 index 000000000..a9c7862fe --- /dev/null +++ b/web/skins/classic/views/frames.php @@ -0,0 +1,103 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ + diff --git a/web/skins/classic/views/function.php b/web/skins/classic/views/function.php new file mode 100644 index 000000000..445450f30 --- /dev/null +++ b/web/skins/classic/views/function.php @@ -0,0 +1,64 @@ + + +
+ +
+
+ + + +

+ + checked="checked"/> +

+
+ + +
+
+
+
+ + diff --git a/web/skins/classic/views/group.php b/web/skins/classic/views/group.php new file mode 100644 index 000000000..bb81774d6 --- /dev/null +++ b/web/skins/classic/views/group.php @@ -0,0 +1,88 @@ + "", + "Name" => "New Group", + "MonitorIds" => "" + ); +} + +xhtmlHeaders( __FILE__, $SLANG['Group']." - ".$newGroup['Name'] ); +?> + +
+ +
+
+ + + + + + + + + + + + + + +
+ +
+
+ disabled="disabled"/> + +
+
+
+
+ + diff --git a/web/skins/classic/views/groups.php b/web/skins/classic/views/groups.php new file mode 100644 index 000000000..87f8b9ebe --- /dev/null +++ b/web/skins/classic/views/groups.php @@ -0,0 +1,94 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
onclick="configureButtons( this );"/>
onclick="configureButtons( this );"/>
+
+ + /> + /> + /> + +
+
+
+
+ + diff --git a/web/skins/classic/views/js/Makefile.am b/web/skins/classic/views/js/Makefile.am new file mode 100644 index 000000000..ba1845e0c --- /dev/null +++ b/web/skins/classic/views/js/Makefile.am @@ -0,0 +1,49 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/classic/views/js + +dist_web_DATA = \ + console.js \ + console.js.php \ + control.js \ + controlpreset.js \ + controlpreset.js.php \ + cycle.js \ + cycle.js.php \ + devices.js \ + donate.js \ + donate.js.php \ + event.js \ + event.js.php \ + events.js \ + events.js.php \ + export.js \ + export.js.php \ + filter.js \ + filter.js.php \ + group.js \ + groups.js \ + log.js \ + login.js \ + Makefile.am \ + monitor.js \ + monitor.js.php \ + monitorpreset.js \ + monitorprobe.js \ + montage.js \ + montage.js.php \ + options.js.php \ + postlogin.js \ + state.js \ + state.js.php \ + timeline.js \ + timeline.js.php \ + user.js \ + version.js \ + version.js.php \ + video.js \ + video.js.php \ + watch.js \ + watch.js.php \ + zone.js \ + zone.js.php diff --git a/web/skins/classic/views/js/Makefile.in b/web/skins/classic/views/js/Makefile.in new file mode 100644 index 000000000..ecaf3b191 --- /dev/null +++ b/web/skins/classic/views/js/Makefile.in @@ -0,0 +1,496 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/classic/views/js +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/classic/views/js +dist_web_DATA = \ + console.js \ + console.js.php \ + control.js \ + controlpreset.js \ + controlpreset.js.php \ + cycle.js \ + cycle.js.php \ + devices.js \ + donate.js \ + donate.js.php \ + event.js \ + event.js.php \ + events.js \ + events.js.php \ + export.js \ + export.js.php \ + filter.js \ + filter.js.php \ + group.js \ + groups.js \ + log.js \ + login.js \ + Makefile.am \ + monitor.js \ + monitor.js.php \ + monitorpreset.js \ + monitorprobe.js \ + montage.js \ + montage.js.php \ + options.js.php \ + postlogin.js \ + state.js \ + state.js.php \ + timeline.js \ + timeline.js.php \ + user.js \ + version.js \ + version.js.php \ + video.js \ + video.js.php \ + watch.js \ + watch.js.php \ + zone.js \ + zone.js.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/classic/views/js/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/classic/views/js/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js new file mode 100644 index 000000000..5182a5fd5 --- /dev/null +++ b/web/skins/classic/views/js/console.js @@ -0,0 +1,65 @@ +function setButtonStates( element ) +{ + var form = element.form; + var checked = 0; + for ( var i = 0; i < form.elements.length; i++ ) + { + if ( form.elements[i].type == "checkbox" ) + { + if ( form.elements[i].checked ) + { + if ( checked++ > 1 ) + break; + } + } + } + $(element).getParent( 'tr' ).toggleClass( 'highlight' ); + form.editBtn.disabled = (checked!=1); + form.deleteBtn.disabled = (checked==0); +} + +function editMonitor( element ) +{ + var form = element.form; + for ( var i = 0; i < form.elements.length; i++ ) + { + if ( form.elements[i].type == "checkbox" ) + { + if ( form.elements[i].checked ) + { + var monitorId = form.elements[i].value; + createPopup( '?view=monitor&mid='+monitorId, 'zmMonitor'+monitorId, 'monitor' ); + form.elements[i].checked = false; + setButtonStates( form.elements[i] ); + //$(form.elements[i]).getParent( 'tr' ).removeClass( 'highlight' ); + break; + } + } + } +} + +function deleteMonitor( element ) +{ + if ( confirm( 'Warning, deleting a monitor also deletes all events and database entries associated with it.\nAre you sure you wish to delete?' ) ) + { + var form = element.form; + form.elements['action'].value = 'delete'; + form.submit(); + } +} + +function reloadWindow() +{ + window.location.replace( thisUrl ); +} + +function initPage() +{ + reloadWindow.periodical( consoleRefreshTimeout ); + if ( showVersionPopup ) + createPopup( '?view=version', 'zmVersion', 'version' ); + if ( showDonatePopup ) + createPopup( '?view=donate', 'zmDonate', 'donate' ); +} + +window.addEvent( 'domready', initPage ); diff --git a/web/skins/classic/views/js/console.js.php b/web/skins/classic/views/js/console.js.php new file mode 100644 index 000000000..90f66a619 --- /dev/null +++ b/web/skins/classic/views/js/console.js.php @@ -0,0 +1,28 @@ +var consoleRefreshTimeout = ; + + 0 ) + { + if ( ZM_DYN_DONATE_REMINDER_TIME < time() ) + { + $showDonatePopup = true; + } + } + else + { + $nextReminder = time() + 30*24*60*60; + dbQuery( "update Config set Value = '".$nextReminder."' where Name = 'ZM_DYN_DONATE_REMINDER_TIME'" ); + } + } +} +?> +var showVersionPopup = ; +var showDonatePopup = ; diff --git a/web/skins/classic/views/js/control.js b/web/skins/classic/views/js/control.js new file mode 100644 index 000000000..819f088d8 --- /dev/null +++ b/web/skins/classic/views/js/control.js @@ -0,0 +1,49 @@ +var controlParms = "view=request&request=control"; +var controlReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, onSuccess: getControlResponse } ); + +function getControlResponse( respObj, respText ) +{ + if ( !respObj ) + return; + //console.log( respText ); + if ( respObj.result != 'Ok' ) + { + alert( "Control response was status = "+respObj.status+"\nmessage = "+respObj.message ); + } +} + +function controlCmd( control, event, xtell, ytell ) +{ + var locParms = "&id="+$('mid').get('value'); + if ( event && (xtell || ytell) ) + { + var xEvent = new Event( event ); + var target = xEvent.target; + var coords = $(target).getCoordinates(); + + var l = coords.left; + var t = coords.top; + var x = xEvent.page.x - l; + var y = xEvent.page.y - t; + + if ( xtell ) + { + var xge = parseInt( (x*100)/coords.width ); + if ( xtell == -1 ) + xge = 100 - xge; + else if ( xtell == 2 ) + xge = 2*(50 - xge); + locParms += "&xge="+xge; + } + if ( ytell ) + { + var yge = parseInt( (y*100)/coords.height ); + if ( ytell == -1 ) + yge = 100 - yge; + else if ( ytell == 2 ) + yge = 2*(50 - yge); + locParms += "&yge="+yge; + } + } + controlReq.send( controlParms+"&control="+control+locParms ); +} diff --git a/web/skins/classic/views/js/controlpreset.js b/web/skins/classic/views/js/controlpreset.js new file mode 100644 index 000000000..ec2629cae --- /dev/null +++ b/web/skins/classic/views/js/controlpreset.js @@ -0,0 +1,14 @@ +function updateLabel() +{ + var presetIndex = $('contentForm').preset.getValue(); + if ( labels[presetIndex] ) + { + $('contentForm').newLabel.value = labels[presetIndex]; + } + else + { + $('contentForm').newLabel.value = ""; + } +} + +window.addEvent( 'domready', updateLabel ); diff --git a/web/skins/classic/views/js/controlpreset.js.php b/web/skins/classic/views/js/controlpreset.js.php new file mode 100644 index 000000000..0aac01bf6 --- /dev/null +++ b/web/skins/classic/views/js/controlpreset.js.php @@ -0,0 +1,9 @@ +var labels = new Array(); +$label ) +{ +?> +labels[] = ""; + diff --git a/web/skins/classic/views/js/cycle.js b/web/skins/classic/views/js/cycle.js new file mode 100644 index 000000000..e799a422e --- /dev/null +++ b/web/skins/classic/views/js/cycle.js @@ -0,0 +1,11 @@ +function nextCycleView() +{ + window.location.replace( '?view=cycle&group='+currGroup+'&mid='+nextMid+'&mode='+mode, cycleRefreshTimeout ); +} + +function initCycle() +{ + nextCycleView.periodical( cycleRefreshTimeout ); +} + +window.addEvent( 'domready', initCycle ); diff --git a/web/skins/classic/views/js/cycle.js.php b/web/skins/classic/views/js/cycle.js.php new file mode 100644 index 000000000..c9dabaec4 --- /dev/null +++ b/web/skins/classic/views/js/cycle.js.php @@ -0,0 +1,5 @@ +var currGroup = ""; +var nextMid = ""; +var mode = ""; + +var cycleRefreshTimeout = ; diff --git a/web/skins/classic/views/js/devices.js b/web/skins/classic/views/js/devices.js new file mode 100644 index 000000000..8191518fc --- /dev/null +++ b/web/skins/classic/views/js/devices.js @@ -0,0 +1,47 @@ +function switchDeviceOn( element, key ) +{ + var form = element.form; + form.view.value = currentView; + form.action.value = 'device'; + form.command.value = 'on'; + form.key.value = key; + form.submit(); +} + +function switchDeviceOff( element, key ) +{ + var form = element.form; + form.view.value = currentView; + form.action.value = 'device'; + form.command.value = 'off'; + form.key.value = key; + form.submit(); +} + +function deleteDevice( element ) +{ + var form = element.form; + form.view.value = currentView; + form.action.value = 'delete'; + form.submit(); +} + +function configureButtons( element, name ) +{ + var form = element.form; + var checked = false; + for (var i = 0; i < form.elements.length; i++) + { + if ( form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + checked = true; + break; + } + } + } + form.deleteBtn.disabled = !checked; +} + +window.focus(); diff --git a/web/skins/classic/views/js/donate.js b/web/skins/classic/views/js/donate.js new file mode 100644 index 000000000..87d99198b --- /dev/null +++ b/web/skins/classic/views/js/donate.js @@ -0,0 +1,14 @@ +function submitForm( element ) +{ + var form = element.form; + if ( form.option.selectedIndex == 0 ) + form.view.value = currentView; + else + form.view.value = 'none'; + form.submit(); +} + +if ( action == "donate" && option == "go" ) +{ + zmWindow(); +} diff --git a/web/skins/classic/views/js/donate.js.php b/web/skins/classic/views/js/donate.js.php new file mode 100644 index 000000000..9d24e392f --- /dev/null +++ b/web/skins/classic/views/js/donate.js.php @@ -0,0 +1,2 @@ +var action = ''; +var option = ''; diff --git a/web/skins/classic/views/js/event.js b/web/skins/classic/views/js/event.js new file mode 100644 index 000000000..a1b2a2e55 --- /dev/null +++ b/web/skins/classic/views/js/event.js @@ -0,0 +1,754 @@ +function setButtonState( element, butClass ) +{ + element.className = butClass; + element.disabled = (butClass != 'inactive'); +} + +function changeScale() +{ + var scale = $('scale').get('value'); + var baseWidth = eventData.Width; + var baseHeight = eventData.Height; + var newWidth = ( baseWidth * scale ) / SCALE_BASE; + var newHeight = ( baseHeight * scale ) / SCALE_BASE; + + streamScale( scale ); + + /*Stream could be an applet so can't use moo tools*/ + var streamImg = document.getElementById('evtStream'); + streamImg.style.width = newWidth + "px"; + streamImg.style.height = newHeight + "px"; +} + +function changeReplayMode() +{ + var replayMode = $('replayMode').get('value'); + + Cookie.write( 'replayMode', replayMode, { duration: 10*365 }) + + refreshWindow(); +} + +var streamParms = "view=request&request=stream&connkey="+connKey; +var streamCmdTimer = null; + +var streamStatus = null; +var lastEventId = 0; + +function getCmdResponse( respObj, respText ) +{ + if ( checkStreamForErrors( "getCmdResponse" ,respObj ) ) + return; + + if ( streamCmdTimer ) + streamCmdTimer = clearTimeout( streamCmdTimer ); + + streamStatus = respObj.status; + + var eventId = streamStatus.event; + if ( eventId != lastEventId ) + { + eventQuery( eventId ); + lastEventId = eventId; + } + if ( streamStatus.paused == true ) + { + $('modeValue').set( 'text', "Paused" ); + $('rate').addClass( 'hidden' ); + streamPause( false ); + } + else + { + $('modeValue').set( 'text', "Replay" ); + $('rateValue').set( 'text', streamStatus.rate ); + $('rate').removeClass( 'hidden' ); + streamPlay( false ); + } + $('progressValue').set( 'text', secsToTime( parseInt(streamStatus.progress) ) ); + $('zoomValue').set( 'text', streamStatus.zoom ); + if ( streamStatus.zoom == "1.0" ) + setButtonState( $('zoomOutBtn'), 'unavail' ); + else + setButtonState( $('zoomOutBtn'), 'inactive' ); + + updateProgressBar(); + + streamCmdTimer = streamQuery.delay( streamTimeout ); +} + +var streamReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getCmdResponse } ); + +function streamPause( action ) +{ + setButtonState( $('pauseBtn'), 'active' ); + setButtonState( $('playBtn'), 'inactive' ); + setButtonState( $('fastFwdBtn'), 'unavail' ); + setButtonState( $('slowFwdBtn'), 'inactive' ); + setButtonState( $('slowRevBtn'), 'inactive' ); + setButtonState( $('fastRevBtn'), 'unavail' ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_PAUSE ); +} + +function streamPlay( action ) +{ + setButtonState( $('pauseBtn'), 'inactive' ); + if (streamStatus) + setButtonState( $('playBtn'), streamStatus.rate==1?'active':'inactive' ); + setButtonState( $('fastFwdBtn'), 'inactive' ); + setButtonState( $('slowFwdBtn'), 'unavail' ); + setButtonState( $('slowRevBtn'), 'unavail' ); + setButtonState( $('fastRevBtn'), 'inactive' ); + if ( action ) + { + streamReq.send( streamParms+"&command="+CMD_PLAY ); + } +} + +function streamFastFwd( action ) +{ + setButtonState( $('pauseBtn'), 'inactive' ); + setButtonState( $('playBtn'), 'inactive' ); + setButtonState( $('fastFwdBtn'), 'inactive' ); + setButtonState( $('slowFwdBtn'), 'unavail' ); + setButtonState( $('slowRevBtn'), 'unavail' ); + setButtonState( $('fastRevBtn'), 'inactive' ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_FASTFWD ); +} + +function streamSlowFwd( action ) +{ + setButtonState( $('pauseBtn'), 'inactive' ); + setButtonState( $('playBtn'), 'inactive' ); + setButtonState( $('fastFwdBtn'), 'unavail' ); + setButtonState( $('slowFwdBtn'), 'active' ); + setButtonState( $('slowRevBtn'), 'inactive' ); + setButtonState( $('fastRevBtn'), 'unavail' ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_SLOWFWD ); + setButtonState( $('pauseBtn'), 'active' ); + setButtonState( $('slowFwdBtn'), 'inactive' ); +} + +function streamSlowRev( action ) +{ + setButtonState( $('pauseBtn'), 'inactive' ); + setButtonState( $('playBtn'), 'inactive' ); + setButtonState( $('fastFwdBtn'), 'unavail' ); + setButtonState( $('slowFwdBtn'), 'inactive' ); + setButtonState( $('slowRevBtn'), 'active' ); + setButtonState( $('fastRevBtn'), 'unavail' ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_SLOWREV ); + setButtonState( $('pauseBtn'), 'active' ); + setButtonState( $('slowRevBtn'), 'inactive' ); +} + +function streamFastRev( action ) +{ + setButtonState( $('pauseBtn'), 'inactive' ); + setButtonState( $('playBtn'), 'inactive' ); + setButtonState( $('fastFwdBtn'), 'inactive' ); + setButtonState( $('slowFwdBtn'), 'unavail' ); + setButtonState( $('slowRevBtn'), 'unavail' ); + setButtonState( $('fastRevBtn'), 'inactive' ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_FASTREV ); +} + +function streamPrev( action ) +{ + streamPlay( false ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_PREV ); +} + +function streamNext( action ) +{ + streamPlay( false ); + if ( action ) + streamReq.send( streamParms+"&command="+CMD_NEXT ); +} + +function streamZoomIn( x, y ) +{ + streamReq.send( streamParms+"&command="+CMD_ZOOMIN+"&x="+x+"&y="+y ); +} + +function streamZoomOut() +{ + streamReq.send( streamParms+"&command="+CMD_ZOOMOUT ); +} + +function streamScale( scale ) +{ + streamReq.send( streamParms+"&command="+CMD_SCALE+"&scale="+scale ); +} + +function streamPan( x, y ) +{ + streamReq.send( streamParms+"&command="+CMD_PAN+"&x="+x+"&y="+y ); +} + +function streamSeek( offset ) +{ + streamReq.send( streamParms+"&command="+CMD_SEEK+"&offset="+offset ); +} + +function streamQuery() +{ + streamReq.send( streamParms+"&command="+CMD_QUERY ); +} + +var slider = null; +var scroll = null; + +function getEventResponse( respObj, respText ) +{ + if ( checkStreamForErrors( "getEventResponse", respObj ) ) + return; + + eventData = respObj.event; + if ( !$('eventStills').hasClass( 'hidden' ) && currEventId != eventData.Id ) + resetEventStills(); + currEventId = eventData.Id; + + $('dataId').set( 'text', eventData.Id ); + if ( eventData.Notes ) + { + $('dataCause').setProperty( 'title', eventData.Notes ); + } + else + { + $('dataCause').setProperty( 'title', causeString ); + } + $('dataCause').set( 'text', eventData.Cause ); + $('dataTime').set( 'text', eventData.StartTime ); + $('dataDuration').set( 'text', eventData.Length ); + $('dataFrames').set( 'text', eventData.Frames+"/"+eventData.AlarmFrames ); + $('dataScore').set( 'text', eventData.TotScore+"/"+eventData.AvgScore+"/"+eventData.MaxScore ); + $('eventName').setProperty( 'value', eventData.Name ); + + if ( canEditEvents ) + { + if ( parseInt(eventData.Archived) ) + { + $('archiveEvent').addClass( 'hidden' ); + $('unarchiveEvent').removeClass( 'hidden' ); + } + else + { + $('archiveEvent').removeClass( 'hidden' ); + $('unarchiveEvent').addClass( 'hidden' ); + } + } + //var eventImg = $('eventImage'); + //eventImg.setStyles( { 'width': eventData.width, 'height': eventData.height } ); + drawProgressBar(); + nearEventsQuery( eventData.Id ); +} + +var eventReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getEventResponse } ); + +function eventQuery( eventId ) +{ + var eventParms = "view=request&request=status&entity=event&id="+eventId; + eventReq.send( eventParms ); +} + +var prevEventId = 0; +var nextEventId = 0; + +function getNearEventsResponse( respObj, respText ) +{ + if ( checkStreamForErrors( "getNearEventsResponse", respObj ) ) + return; + prevEventId = respObj.nearevents.PrevEventId; + nextEventId = respObj.nearevents.NextEventId; + + $('prevEventBtn').disabled = !prevEventId; + $('nextEventBtn').disabled = !nextEventId; +} + +var nearEventsReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getNearEventsResponse } ); + +function nearEventsQuery( eventId ) +{ + var parms = "view=request&request=status&entity=nearevents&id="+eventId; + nearEventsReq.send( parms ); +} + +var frameBatch = 40; + +function loadEventThumb( event, frame, loadImage ) +{ + var thumbImg = $('eventThumb'+frame.FrameId); + if ( !thumbImg ) + { + console.error( "No holder found for frame "+frame.FrameId ); + return; + } + var img = new Asset.image( imagePrefix+frame.Image.imagePath, + { + 'onload': ( function( loadImage ) + { + thumbImg.setProperty( 'src', img.getProperty( 'src' ) ); + thumbImg.removeClass( 'placeholder' ); + thumbImg.setProperty( 'class', frame.Type=='Alarm'?'alarm':'normal' ); + thumbImg.setProperty( 'title', frame.FrameId+' / '+((frame.Type=='Alarm')?frame.Score:0) ); + thumbImg.removeEvents( 'click' ); + thumbImg.addEvent( 'click', function() { locateImage( frame.FrameId, true ); } ); + if ( loadImage ) + loadEventImage( event, frame ); + } ).pass( loadImage ) + } + ); +} + +function updateStillsSizes( noDelay ) +{ + var containerDim = $('eventThumbs').getSize(); + + var containerWidth = containerDim.x; + var containerHeight = containerDim.y; + var popupWidth = parseInt($('eventImage').getStyle( 'width' )); + var popupHeight = parseInt($('eventImage').getStyle( 'height' )); + + var left = (containerWidth - popupWidth)/2; + if ( left < 0 ) left = 0; + var top = (containerHeight - popupHeight)/2; + if ( top < 0 ) top = 0; + if ( popupHeight == 0 && !noDelay ) // image not yet loaded lets give it another second + { + updateStillsSizes.pass( true ).delay( 50 ); + return; + } + $('eventImagePanel').setStyles( { + 'left': left, + 'top': top + } ); +} + +function loadEventImage( event, frame ) +{ + console.debug( "Loading "+event.Id+"/"+frame.FrameId ); + var eventImg = $('eventImage'); + var thumbImg = $('eventThumb'+frame.FrameId); + if ( eventImg.getProperty( 'src' ) != thumbImg.getProperty( 'src' ) ) + { + var eventImagePanel = $('eventImagePanel'); + + if ( eventImagePanel.getStyle( 'display' ) != 'none' ) + { + var lastThumbImg = $('eventThumb'+eventImg.getProperty( 'alt' )); + lastThumbImg.removeClass('selected'); + lastThumbImg.setOpacity( 1.0 ); + } + + eventImg.setProperties( { + 'class': frame.Type=='Alarm'?'alarm':'normal', + 'src': thumbImg.getProperty( 'src' ), + 'title': thumbImg.getProperty( 'title' ), + 'alt': thumbImg.getProperty( 'alt' ), + 'width': event.Width, + 'height': event.Height + } ); + $('eventImageBar').setStyle( 'width', event.Width ); + if ( frame.Type=='Alarm' ) + $('eventImageStats').removeClass( 'hidden' ); + else + $('eventImageStats').addClass( 'hidden' ); + thumbImg.addClass( 'selected' ); + thumbImg.setOpacity( 0.5 ); + + if ( eventImagePanel.getStyle( 'display' ) == 'none' ) + { + eventImagePanel.setOpacity( 0 ); + updateStillsSizes(); + eventImagePanel.setStyle( 'display', 'block' ); + new Fx.Tween( eventImagePanel, { duration: 500, transition: Fx.Transitions.Sine } ).start( 'opacity', 0, 1 ); + } + + $('eventImageNo').set( 'text', frame.FrameId ); + $('prevImageBtn').disabled = (frame.FrameId==1); + $('nextImageBtn').disabled = (frame.FrameId==event.Frames); + } +} + +function hideEventImageComplete() +{ + var eventImg = $('eventImage'); + var thumbImg = $('eventThumb'+$('eventImage').getProperty( 'alt' )); + thumbImg.removeClass('selected'); + thumbImg.setOpacity( 1.0 ); + $('prevImageBtn').disabled = true; + $('nextImageBtn').disabled = true; + $('eventImagePanel').setStyle( 'display', 'none' ); + $('eventImageStats').addClass( 'hidden' ); +} + +function hideEventImage() +{ + if ( $('eventImagePanel').getStyle( 'display' ) != 'none' ) + new Fx.Tween( $('eventImagePanel'), { duration: 500, transition: Fx.Transitions.Sine, onComplete: hideEventImageComplete } ).start( 'opacity', 1, 0 ); +} + +function resetEventStills() +{ + hideEventImage(); + $('eventThumbs').empty(); + if ( true || !slider ) + { + slider = new Slider( $('thumbsSlider'), $('thumbsKnob'), { + /*steps: eventData.Frames,*/ + onChange: function( step ) + { + if ( !step ) + step = 0; + var fid = parseInt((step * eventData.Frames)/this.options.steps); + if ( fid < 1 ) + fid = 1; + else if ( fid > eventData.Frames ) + fid = eventData.Frames; + checkFrames( eventData.Id, fid ); + scroll.toElement( 'eventThumb'+fid ); + } + } ).set( 0 ); + } + if ( $('eventThumbs').getStyle( 'height' ).match( /^\d+/ ) < (parseInt(eventData.Height)+80) ) + $('eventThumbs').setStyle( 'height', (parseInt(eventData.Height)+80)+'px' ); +} + +function getFrameResponse( respObj, respText ) +{ + if ( checkStreamForErrors( "getFrameResponse", respObj ) ) + return; + + var frame = respObj.frameimage; + + if ( !eventData ) + { + console.error( "No event "+frame.EventId+" found" ); + return; + } + + if ( !eventData['frames'] ) + eventData['frames'] = new Object(); + + eventData['frames'][frame.FrameId] = frame; + + loadEventThumb( eventData, frame, respObj.loopback=="true" ); +} + +var frameReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain', onSuccess: getFrameResponse } ); + +function frameQuery( eventId, frameId, loadImage ) +{ + var parms = "view=request&request=status&entity=frameimage&id[0]="+eventId+"&id[1]="+frameId+"&loopback="+loadImage; + frameReq.send( parms ); +} + +var currFrameId = null; + +function checkFrames( eventId, frameId, loadImage ) +{ + if ( !eventData ) + { + console.error( "No event "+eventId+" found" ); + return; + } + + if ( !eventData['frames'] ) + eventData['frames'] = new Object(); + + currFrameId = frameId; + + var loFid = frameId - frameBatch/2; + if ( loFid < 1 ) + loFid = 1; + var hiFid = loFid + (frameBatch-1); + if ( hiFid > eventData.Frames ) + hiFid = eventData.Frames; + + for ( var fid = loFid; fid <= hiFid; fid++ ) + { + if ( !$('eventThumb'+fid) ) + { + var img = new Element( 'img', { 'id': 'eventThumb'+fid, 'src': 'graphics/transparent.gif', 'alt': fid, 'class': 'placeholder' } ); + img.addEvent( 'click', function () { eventData['frames'][fid] = null; checkFrames( eventId, fid ) } ); + frameQuery( eventId, fid, loadImage && (fid == frameId) ); + var imgs = $('eventThumbs').getElements( 'img' ); + var injected = false; + if ( fid < imgs.length ) + { + img.inject( imgs[fid-1], 'before' ); + injected = true; + } + else + { + injected = imgs.some( + function( thumbImg, index ) + { + if ( parseInt(img.getProperty( 'alt' )) < parseInt(thumbImg.getProperty( 'alt' )) ) + { + img.inject( thumbImg, 'before' ); + return( true ); + } + return( false ); + } + ); + } + if ( !injected ) + { + img.inject( $('eventThumbs') ); + } + var scale = parseInt(img.getStyle('height')); + img.setStyles( { + 'width': parseInt((eventData.Width*scale)/100), + 'height': parseInt((eventData.Height*scale)/100) + } ); + } + else if ( eventData['frames'][fid] ) + { + if ( loadImage && (fid == frameId) ) + { + loadEventImage( eventData, eventData['frames'][fid], loadImage ); + } + } + } + $('prevThumbsBtn').disabled = (frameId==1); + $('nextThumbsBtn').disabled = (frameId==eventData.Frames); +} + +function locateImage( frameId, loadImage ) +{ + if ( slider ) + slider.fireEvent( 'tick', slider.toPosition( parseInt((frameId-1)*slider.options.steps/eventData.Frames) )); + checkFrames( eventData.Id, frameId, loadImage ); + scroll.toElement( 'eventThumb'+frameId ); +} + +function prevImage() +{ + if ( currFrameId > 1 ) + locateImage( parseInt(currFrameId)-1, true ); +} + +function nextImage() +{ + if ( currFrameId < eventData.Frames ) + locateImage( parseInt(currFrameId)+1, true ); +} + +function prevThumbs() +{ + if ( currFrameId > 1 ) + locateImage( parseInt(currFrameId)>10?(parseInt(currFrameId)-10):1, $('eventImagePanel').getStyle('display')!="none" ); +} + +function nextThumbs() +{ + if ( currFrameId < eventData.Frames ) + locateImage( parseInt(currFrameId)<(eventData.Frames-10)?(parseInt(currFrameId)+10):eventData.Frames, $('eventImagePanel').getStyle('display')!="none" ); +} + +function prevEvent() +{ + if ( prevEventId ) + { + eventQuery( prevEventId ); + streamPrev( true ); + } +} + +function nextEvent() +{ + if ( nextEventId ) + { + eventQuery( nextEventId ); + streamNext( true ); + } +} + +function getActResponse( respObj, respText ) +{ + if ( checkStreamForErrors( "getActResponse", respObj ) ) + return; + + if ( respObj.refreshParent ) + refreshParentWindow(); + + if ( respObj.refreshEvent ) + eventQuery( eventData.Id ); +} + +var actReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'cancel', onSuccess: getActResponse } ); + +function actQuery( action, parms ) +{ + var actParms = "view=request&request=event&id="+eventData.Id+"&action="+action; + if ( parms != null ) + actParms += "&"+Object.toQueryString( parms ); + actReq.send( actParms ); +} + +function deleteEvent() +{ + actQuery( 'delete' ); + streamNext( true ); +} + +function renameEvent() +{ + var newName = $('eventName').get('value'); + actQuery( 'rename', { eventName: newName } ); +} + +function editEvent() +{ + createPopup( '?view=eventdetail&eid='+eventData.Id, 'zmEventDetail', 'eventdetail' ); +} + +function exportEvent() +{ + createPopup( '?view=export&eid='+eventData.Id, 'zmExport', 'export' ); +} + +function archiveEvent() +{ + actQuery( 'archive' ); +} + +function unarchiveEvent() +{ + actQuery( 'unarchive' ); +} + +function showEventFrames() +{ + createPopup( '?view=frames&eid='+eventData.Id, 'zmFrames', 'frames' ); +} + +function showStream() +{ + $('eventStills').addClass( 'hidden' ); + $('eventStream').removeClass( 'hidden' ); + $('streamEvent').addClass( 'hidden' ); + $('stillsEvent').removeClass( 'hidden' ); + + //$(window).removeEvent( 'resize', updateStillsSizes ); +} + +function showStills() +{ + $('eventStream').addClass( 'hidden' ); + $('eventStills').removeClass( 'hidden' ); + $('stillsEvent').addClass( 'hidden' ); + $('streamEvent').removeClass( 'hidden' ); + streamPause( true ); + if ( !scroll ) + { + scroll = new Fx.Scroll( 'eventThumbs', { + wait: false, + duration: 500, + offset: { 'x': 0, 'y': 0 }, + transition: Fx.Transitions.Quad.easeInOut + } + ); + } + resetEventStills(); + $(window).addEvent( 'resize', updateStillsSizes ); +} + +function showFrameStats() +{ + var fid = $('eventImageNo').get('text'); + createPopup( '?view=stats&eid='+eventData.Id+'&fid='+fid, 'zmStats', 'stats', eventData.Width, eventData.Height ); +} + +function videoEvent() +{ + createPopup( '?view=video&eid='+eventData.Id, 'zmVideo', 'video', eventData.Width, eventData.Height ); +} + +function drawProgressBar() +{ + var barWidth = 0; + $('progressBar').addClass( 'invisible' ); + var cells = $('progressBar').getElements( 'div' ); + var cellWidth = parseInt( eventData.Width/$$(cells).length ); + $$(cells).forEach( + function( cell, index ) + { + if ( index == 0 ) + $(cell).setStyles( { 'left': barWidth, 'width': cellWidth, 'borderLeft': 0 } ); + else + $(cell).setStyles( { 'left': barWidth, 'width': cellWidth } ); + var offset = parseInt((index*eventData.Length)/$$(cells).length); + $(cell).setProperty( 'title', '+'+secsToTime(offset)+'s' ); + $(cell).removeEvent( 'click' ); + $(cell).addEvent( 'click', function(){ streamSeek( offset ); } ); + barWidth += $(cell).getCoordinates().width; + } + ); + $('progressBar').setStyle( 'width', barWidth ); + $('progressBar').removeClass( 'invisible' ); +} + +function updateProgressBar() +{ + if ( eventData && streamStatus ) + { + var cells = $('progressBar').getElements( 'div' ); + var completeIndex = parseInt((($$(cells).length+1)*streamStatus.progress)/eventData.Length); + $$(cells).forEach( + function( cell, index ) + { + if ( index < completeIndex ) + { + if ( !$(cell).hasClass( 'complete' ) ) + { + $(cell).addClass( 'complete' ); + } + } + else + { + if ( $(cell).hasClass( 'complete' ) ) + { + $(cell).removeClass( 'complete' ); + } + } + } + ); + } +} + +function handleClick( event ) +{ + var target = event.target; + var x = event.page.x - $(target).getLeft(); + var y = event.page.y - $(target).getTop(); + + if ( event.shift ) + streamPan( x, y ); + else + streamZoomIn( x, y ); +} + +function initPage() +{ + streamCmdTimer = streamQuery.delay( 250 ); + eventQuery.pass( eventData.Id ).delay( 500 ); + + if ( canStreamNative ) + { + var streamImg = $('imageFeed').getElement('img'); + if ( !streamImg ) + streamImg = $('imageFeed').getElement('object'); + $(streamImg).addEvent( 'click', function( event ) { handleClick( event ); } ); + } +} + +// Kick everything off +window.addEvent( 'domready', initPage ); diff --git a/web/skins/classic/views/js/event.js.php b/web/skins/classic/views/js/event.js.php new file mode 100644 index 000000000..9ae458651 --- /dev/null +++ b/web/skins/classic/views/js/event.js.php @@ -0,0 +1,48 @@ +// +// Import constants +// +var CMD_NONE = ; +var CMD_PAUSE = ; +var CMD_PLAY = ; +var CMD_STOP = ; +var CMD_FASTFWD = ; +var CMD_SLOWFWD = ; +var CMD_SLOWREV = ; +var CMD_FASTREV = ; +var CMD_ZOOMIN = ; +var CMD_ZOOMOUT = ; +var CMD_PAN = ; +var CMD_SCALE = ; +var CMD_PREV = ; +var CMD_NEXT = ; +var CMD_SEEK = ; +var CMD_QUERY = ; + +var SCALE_BASE = ; + +// +// PHP variables to JS +// +var connKey = ''; + +var eventData = { + Id: , + Width: , + Height: , + Length: +}; + +var filterQuery = ''; +var sortQuery = ''; + +var scale = ; +var canEditEvents = ; +var streamTimeout = ; + +var canStreamNative = ; + +// +// Strings +// +var deleteString = ""; +var causeString = ""; diff --git a/web/skins/classic/views/js/events.js b/web/skins/classic/views/js/events.js new file mode 100644 index 000000000..6aa129932 --- /dev/null +++ b/web/skins/classic/views/js/events.js @@ -0,0 +1,150 @@ +function closeWindows() +{ + window.close(); + // This is a hack. The only way to close an existing window is to try and open it! + var filterWindow = window.open( thisUrl+'?view=none', 'zmFilter', 'width=1,height=1' ); + filterWindow.close(); +} + +function toggleCheckbox( element, name ) +{ + var form = element.form; + var checked = element.checked; + for (var i = 0; i < form.elements.length; i++) + if (form.elements[i].name.indexOf(name) == 0) + form.elements[i].checked = checked; + form.viewBtn.disabled = !checked; + form.editBtn.disabled = !checked; + form.archiveBtn.disabled = unarchivedEvents?!checked:true; + form.unarchiveBtn.disabled = archivedEvents?!checked:true; + form.exportBtn.disabled = !checked; + form.deleteBtn.disabled = !checked; +} + +function configureButton( element, name ) +{ + var form = element.form; + var checked = element.checked; + if ( !checked ) + { + for (var i = 0; i < form.elements.length; i++) + { + if ( form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + checked = true; + break; + } + } + } + } + if ( !element.checked ) + form.toggleCheck.checked = false; + form.viewBtn.disabled = !checked; + form.editBtn.disabled = !checked; + form.archiveBtn.disabled = (!checked)||(!unarchivedEvents); + form.unarchiveBtn.disabled = (!checked)||(!archivedEvents); + form.exportBtn.disabled = !checked; + form.deleteBtn.disabled = !checked; +} + +function deleteEvents( element, name ) +{ + var form = element.form; + var count = 0; + for (var i = 0; i < form.elements.length; i++) + { + if (form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + count++; + break; + } + } + } + if ( count > 0 ) + { + if ( confirm( confirmDeleteEventsString ) ) + { + form.action.value = 'delete'; + form.submit(); + } + } +} + +function editEvents( element, name ) +{ + var form = element.form; + var eids = new Array(); + for (var i = 0; i < form.elements.length; i++) + { + if (form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + eids[eids.length] = 'eids[]='+form.elements[i].value; + } + } + } + createPopup( '?view=eventdetail&'+eids.join( '&' ), 'zmEventDetail', 'eventdetail' ); +} + +function exportEvents( element, name ) +{ + var form = element.form; + var eids = new Array(); + for (var i = 0; i < form.elements.length; i++) + { + if (form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + eids[eids.length] = 'eids[]='+form.elements[i].value; + } + } + } + createPopup( '?view=export&'+eids.join( '&' ), 'zmExport', 'export' ); +} + +function viewEvents( element, name ) +{ + var form = element.form; + var events = new Array(); + for (var i = 0; i < form.elements.length; i++) + { + if ( form.elements[i].name.indexOf(name) == 0) + { + if ( form.elements[i].checked ) + { + events[events.length] = form.elements[i].value; + } + } + } + if ( events.length > 0 ) + { + createPopup( '?view=event&eid='+events[0]+'&filter[terms][0][attr]=Id&&filter[terms][0][op]=%3D%5B%5D&&filter[terms][0][val]='+events.join('%2C')+sortQuery+'&page=1&play=1', 'zmEvent', 'event', maxWidth, maxHeight ); + } +} + +function archiveEvents( element, name ) +{ + var form = element.form; + form.action.value = 'archive'; + form.submit(); +} + +function unarchiveEvents( element, name ) +{ + var form = element.form; + form.action.value = 'unarchive'; + form.submit(); +} + +if ( openFilterWindow ) +{ + //opener.location.reload(true); + createPopup( '?view=filter&page='+thisPage+filterQuery, 'zmFilter', 'filter' ); + location.replace( '?view='+currentView+'&page='+thisPage+filterQuery ); +} diff --git a/web/skins/classic/views/js/events.js.php b/web/skins/classic/views/js/events.js.php new file mode 100644 index 000000000..497d0c96e --- /dev/null +++ b/web/skins/classic/views/js/events.js.php @@ -0,0 +1,13 @@ +//var openFilterWindow = ; +var openFilterWindow = false; + +var archivedEvents = ; +var unarchivedEvents = ; + +var filterQuery = ''; +var sortQuery = ''; + +var maxWidth = ; +var maxHeight = ; + +var confirmDeleteEventsString = ""; diff --git a/web/skins/classic/views/js/export.js b/web/skins/classic/views/js/export.js new file mode 100644 index 000000000..482b41d72 --- /dev/null +++ b/web/skins/classic/views/js/export.js @@ -0,0 +1,58 @@ +function configureExportButton( element ) +{ + var form = element.form; + + var checkCount = 0; + var radioCount = 0; + for ( var i = 0; i < form.elements.length; i++ ) + if ( form.elements[i].type == "checkbox" && form.elements[i].checked ) + checkCount++; + else if ( form.elements[i].type == "radio" && form.elements[i].checked ) + radioCount++; + form.elements['exportButton'].disabled = (checkCount == 0 || radioCount == 0); +} + +function startDownload( exportFile ) +{ + window.location.replace( exportFile ); +} + +var exportTimer = null; + +function exportProgress() +{ + var tickerText = $('exportProgressTicker').get('text'); + if ( tickerText.length < 1 || tickerText.length > 4 ) + $('exportProgressTicker').set( 'text', '.' ); + else + $('exportProgressTicker').appendText( '.' ); +} + +function exportResponse( respObj, respText ) +{ + window.location.replace( thisUrl+'?view='+currentView+'&'+eidParm+'&exportFile='+respObj.exportFile+'&generated='+((respObj.result=='Ok')?1:0) ); +} + +function exportEvent( form ) +{ + var parms = 'view=request&request=event&action=export'; + parms += '&'+$(form).toQueryString(); + var query = new Request.JSON( { url: thisUrl, method: 'post', data: parms, onSuccess: exportResponse } ); + query.send(); + $('exportProgress').removeClass( 'hidden' ); + $('exportProgress').setProperty( 'class', 'warnText' ); + $('exportProgressText').set( 'text', exportProgressString ); + exportProgress(); + exportTimer = exportProgress.periodical( 500 ); +} + +function initPage() +{ + configureExportButton( $('exportButton') ); + if ( exportReady ) + { + startDownload.pass( exportFile ).delay( 1500 ); + } +} + +window.addEvent( 'domready', initPage ); diff --git a/web/skins/classic/views/js/export.js.php b/web/skins/classic/views/js/export.js.php new file mode 100644 index 000000000..e51089c14 --- /dev/null +++ b/web/skins/classic/views/js/export.js.php @@ -0,0 +1,22 @@ + +var eidParm = ''; + +var eidParm = 'eid='; + + +var exportReady = ; +var exportFile = ''; + +var exportProgressString = ''; diff --git a/web/skins/classic/views/js/filter.js b/web/skins/classic/views/js/filter.js new file mode 100644 index 000000000..840ca04e0 --- /dev/null +++ b/web/skins/classic/views/js/filter.js @@ -0,0 +1,120 @@ +function updateButtons( element ) +{ + var form = element.form; + + if ( element.type == 'checkbox' && element.checked ) + form.elements['executeButton'].disabled = false; + else + { + var canExecute = false; + if ( form.elements['autoArchive'].checked ) + canExecute = true; + if ( form.elements['autoVideo'].checked ) + canExecute = true; + if ( form.elements['autoUpload'].checked ) + canExecute = true; + if ( form.elements['autoEmail'].checked ) + canExecute = true; + if ( form.elements['autoMessage'].checked ) + canExecute = true; + if ( form.elements['autoExecute'].checked && form.elements['autoExecuteCmd'].value != '' ) + canExecute = true; + if ( form.elements['autoDelete'].checked ) + canExecute = true; + form.elements['executeButton'].disabled = !canExecute; + } +} + +function clearValue( element, line ) +{ + var form = element.form; + var val = form.elements['filter[terms]['+line+'][val]']; + val.value = ''; +} + +function submitToFilter( element, reload ) +{ + var form = element.form; + form.target = window.name; + form.view.value = 'filter'; + form.reload.value = reload; + form.submit(); +} + +function submitToEvents( element ) +{ + var form = element.form; + if ( validateForm( form ) ) + { + form.target = 'zmEvents'; + form.view.value = 'events'; + form.action.value = ''; + form.execute.value = 0; + form.submit(); + } +} + +function executeFilter( element ) +{ + var form = element.form; + if ( validateForm( form ) ) + { + form.target = 'zmEvents'; + form.view.value = 'events'; + form.action.value = 'filter'; + form.execute.value = 1; + form.submit(); + } +} + +function saveFilter( element ) +{ + var form = element.form; + + var popupName = 'zmEventsFilterSave'; + createPopup( thisUrl, popupName, 'filtersave' ); + + form.target = popupName; + form.view.value = 'filtersave'; + form.submit(); +} + +function deleteFilter( element, name ) +{ + if ( confirm( deleteSavedFilterString+" '"+name+"'" ) ) + { + var form = element.form; + form.action.value = 'delete'; + form.fid.value = name; + submitToFilter( element, 1 ); + } +} + +function addTerm( element, line ) +{ + var form = element.form; + form.target = window.name; + form.view.value = currentView; + form.action.value = 'filter'; + form.subaction.value = 'addterm'; + form.line.value = line; + form.submit(); +} + +function delTerm( element, line ) +{ + var form = element.form; + form.target = window.name; + form.view.value = currentView; + form.action.value = 'filter'; + form.subaction.value = 'delterm'; + form.line.value = line; + form.submit(); +} + +function init() +{ + updateButtons( $('executeButton') ); +} + +window.addEvent( 'domready', init ); diff --git a/web/skins/classic/views/js/filter.js.php b/web/skins/classic/views/js/filter.js.php new file mode 100644 index 000000000..c83a27a39 --- /dev/null +++ b/web/skins/classic/views/js/filter.js.php @@ -0,0 +1,56 @@ +var deleteSavedFilterString = ""; + +function validateForm( form ) +{ + 2 ) +{ +?> + var bracket_count = 0; + + var obr = form.elements['filter[terms][][obr]']; + var cbr = form.elements['filter[terms][][cbr]']; + bracket_count += parseInt(obr.options[obr.selectedIndex].value); + bracket_count -= parseInt(cbr.options[cbr.selectedIndex].value); + + if ( bracket_count ) + { + alert( "" ); + return( false ); + } + + + var val = form.elements['filter[terms][][val]']; + if ( val.value == '' ) + { + alert( "" ); + return( false ); + } + + return( true ); +} + + + + + + + + + + + + + + diff --git a/web/skins/classic/views/optionhelp.php b/web/skins/classic/views/optionhelp.php new file mode 100644 index 000000000..5ac37527b --- /dev/null +++ b/web/skins/classic/views/optionhelp.php @@ -0,0 +1,44 @@ +", $optionHelpText ); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['OptionHelp'] ); +?> + +
+ +
+

+

+
+
+ + diff --git a/web/skins/classic/views/options.php b/web/skins/classic/views/options.php new file mode 100644 index 000000000..e87aa542a --- /dev/null +++ b/web/skins/classic/views/options.php @@ -0,0 +1,324 @@ + + +
+ +
+
    +$value ) +{ + if ( $tab == $name ) + { +?> +
  • + +
  • + +
+
+window.opener.location.reload();window.location.reload();'; + } + +?> +
+ + + + + + + + +
ZM_SKIN +
+
+ /> + +
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
disabled="disabled"/>
+
+ disabled="disabled"/> +
+
+ +
+ + + + + + + + + + + + +$value ) + { + $shortName = preg_replace( '/^ZM_/', '', $name ); + $optionPromptText = !empty($OLANG[$shortName])?$OLANG[$shortName]:$value['Prompt']; +?> + + + + + + + + + + + + + + + + + + + + + +
 () checked="checked"/> + 3 ) + { +?> + + + checked="checked"/>  + + />/>/>/>
+
+ /> +
+
+ +
+
+ + diff --git a/web/skins/classic/views/plugin.php b/web/skins/classic/views/plugin.php new file mode 100644 index 000000000..91795be77 --- /dev/null +++ b/web/skins/classic/views/plugin.php @@ -0,0 +1,170 @@ + 0 ) +{ + $newZone = dbFetchOne( "select * from Zones where MonitorId = '".dbEscape($mid)."' and Id = '".dbEscape($zid)."'" ); +} else { + $view = "error"; + return; +} +$monitor = dbFetchMonitor ( $mid ); +$plugin = dbEscape($_REQUEST['pl']); + +$plugin_path = dirname(ZM_PLUGINS_CONFIG_PATH)."/".$plugin; + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Plugin'] ); + + +$pluginOptions=array( + 'Enabled'=>array( + 'Type'=>'select', + 'Name'=>'Enabled', + 'Choices'=>'yes,no', + 'Value'=>'no' + ) + ); + +$optionNames=array(); +if(file_exists($plugin_path."/config.php")) +{ + include_once($plugin_path."/config.php"); +} + +$sql="SELECT * FROM PluginsConfig WHERE MonitorId=$mid AND ZoneId=$zid AND pluginName='$plugin'"; +foreach( dbFetchAll( $sql ) as $popt ) +{ + if(array_key_exists($popt['Name'], $pluginOptions) + && $popt['Type']==$pluginOptions[$popt['Name']]['Type'] + && $popt['Choices']==$pluginOptions[$popt['Name']]['Choices'] + ) + { + $pluginOptions[$popt['Name']]=$popt; + array_push($optionNames, $popt['Name']); + } else { + dbQuery("DELETE from PluginsConfig WHERE Id=".$popt['Id']); + } +} +foreach($pluginOptions as $name => $values) +{ + if(!in_array($name, $optionNames)) + { + $popt=$pluginOptions[$name]; + $sql="INSERT INTO PluginsConfig VALUES + ('','".dbEscape($popt['Name'])."','".dbEscape($popt['Value'])."', + '".dbEscape($popt['Type'])."','".dbEscape($popt['Choices'])."','$mid','$zid','$plugin')"; + dbQuery($sql); + } +} + +$PLANG=array(); +if(file_exists($plugin_path."/lang/".$user['Language'].".php")) { + include_once($plugin_path."/lang/".$user['Language'].".php"); +} + +function pLang($name) +{ + global $PLANG; + if(array_key_exists($name, $PLANG)) + return $PLANG[$name]; + else + return $name; +} + + +?> + +
+ +
+
+ + + + + + +
+ + + $popt) +{ + ?> + + + + + + + + +
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/postlogin.php b/web/skins/classic/views/postlogin.php new file mode 100644 index 000000000..2ce1ff88f --- /dev/null +++ b/web/skins/classic/views/postlogin.php @@ -0,0 +1,33 @@ + + +
+ +
+

+
+
+ + diff --git a/web/skins/classic/views/settings.php b/web/skins/classic/views/settings.php new file mode 100644 index 000000000..dcc0316f5 --- /dev/null +++ b/web/skins/classic/views/settings.php @@ -0,0 +1,78 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + +
disabled="disabled"/>
disabled="disabled"/>
disabled="disabled"/>
disabled="disabled"/>
+
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/state.php b/web/skins/classic/views/state.php new file mode 100644 index 000000000..4e8365d51 --- /dev/null +++ b/web/skins/classic/views/state.php @@ -0,0 +1,106 @@ + + +
+ +
+
+ + + + +

+ +

+ + + + + + + +
+
+ + + + +
+ + + + +

+

+ +
+
+
+ + diff --git a/web/skins/classic/views/stats.php b/web/skins/classic/views/stats.php new file mode 100644 index 000000000..a1668bc8e --- /dev/null +++ b/web/skins/classic/views/stats.php @@ -0,0 +1,111 @@ + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + 1 ) +{ +?> + + + + + + + + + + + + + +
+
+
+
+ + diff --git a/web/skins/classic/views/status.php b/web/skins/classic/views/status.php new file mode 100644 index 000000000..113c23d88 --- /dev/null +++ b/web/skins/classic/views/status.php @@ -0,0 +1,85 @@ + + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+
+ + diff --git a/web/skins/classic/views/timeline.php b/web/skins/classic/views/timeline.php new file mode 100644 index 000000000..d137b8bfd --- /dev/null +++ b/web/skins/classic/views/timeline.php @@ -0,0 +1,974 @@ +700, + "height"=>460, + "image" => array( + "width"=>264, + "height"=>220, + "topOffset"=>20, + ), + "imageText" => array( + "width"=>400, + "height"=>30, + "topOffset"=>20, + ), + "graph" => array( + "width"=>600, + "height"=>160, + "topOffset"=>30, + ), + "title" => array( + "topOffset"=>50 + ), + "key" => array( + "topOffset"=>50 + ), + "axes" => array( + "x" => array( + "height" => 20, + ), + "y" => array( + "width" => 30, + ), + ), + "grid" => array( + "x" => array( + "major" => array( + "max" => 12, + "min" => 4, + ), + "minor" => array( + "max" => 48, + "min" => 12, + ), + ), + "y" => array( + "major" => array( + "max" => 8, + "min" => 1, + ), + "minor" => array( + "max" => 0, + "min" => 0, + ), + ), + ), +); + +$monitors = array(); +$monitorsSql = "select * from Monitors order by Sequence asc"; +//srand( 97981 ); +foreach( dbFetchAll( $monitorsSql ) as $row ) +{ + //if ( empty($row['WebColour']) ) + //{ + //$row['WebColour'] = sprintf( "#%02x%02x%02x", rand( 0, 255 ), rand( 0, 255), rand( 0, 255 ) ); + //} + $monitors[$row['Id']] = $row; +} + +$rangeSql = "select min(E.StartTime) as MinTime, max(E.EndTime) as MaxTime from Events as E inner join Monitors as M on (E.MonitorId = M.Id) where not isnull(E.StartTime) and not isnull(E.EndTime)"; +$eventsSql = "select E.Id,E.Name,E.StartTime,E.EndTime,E.Length,E.Frames,E.MaxScore,E.Cause,E.Notes,E.Archived,E.MonitorId from Events as E inner join Monitors as M on (E.MonitorId = M.Id) where not isnull(StartTime)"; + +if ( !empty($user['MonitorIds']) ) +{ + $monFilterSql = " and M.Id in (".join( ",", preg_split( '/["\'\s]*,["\'\s]*/', $user['MonitorIds'] ) ).")"; + + $rangeSql .= $monFilterSql; + $eventsSql .= $monFilterSql; +} + +if ( isset($_REQUEST['filter']) ) + $tree = parseFilterToTree( $_REQUEST['filter'] ); +else + $tree = false; + +if ( isset($_REQUEST['range']) ) + $range = validHtmlStr($_REQUEST['range']); +if ( isset($_REQUEST['minTime']) ) + $minTime = validHtmlStr($_REQUEST['minTime']); +if ( isset($_REQUEST['midTime']) ) + $midTime = validHtmlStr($_REQUEST['midTime']); +if ( isset($_REQUEST['maxTime']) ) + $maxTime = validHtmlStr($_REQUEST['maxTime']); + +if ( isset($range) ) +{ + $halfRange = (int)($range/2); + if ( isset($midTime) ) + { + $midTimeT = strtotime($midTime); + $minTimeT = $midTimeT-$halfRange; + $maxTimeT = $midTimeT+$halfRange; + if ( !($range%1) ) + { + $maxTimeT--; + } + $minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT ); + $maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT ); + } + elseif ( isset($minTime) ) + { + $minTimeT = strtotime($minTime); + $maxTimeT = $minTimeT + $range; + $midTimeT = $minTimeT + $halfRange; + $midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT ); + $maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT ); + } + elseif ( isset($maxTime) ) + { + $maxTimeT = strtotime($maxTime); + $minTimeT = $maxTimeT - $range; + $midTimeT = $minTimeT + $halfRange; + $minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT ); + $midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT ); + } +} +elseif ( isset($minTime) && isset($maxTime) ) +{ + $minTimeT = strtotime($minTime); + $maxTimeT = strtotime($maxTime); + $range = ($maxTimeT - $minTimeT) + 1; + $halfRange = (int)($range/2); + $midTimeT = $minTimeT + $halfRange; + $midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT ); +} + +if ( isset($minTime) && isset($maxTime) ) +{ + $tempMinTime = $tempMaxTime = $tempExpandable = false; + extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable ); + $filterSql = parseTreeToSQL( $tree ); + + if ( $filterSql ) + { + $filterSql = " and $filterSql"; + $eventsSql .= $filterSql; + } +} +else +{ + $filterSql = parseTreeToSQL( $tree ); + $tempMinTime = $tempMaxTime = $tempExpandable = false; + extractDatetimeRange( $tree, $tempMinTime, $tempMaxTime, $tempExpandable ); + + if ( $filterSql ) + { + $filterSql = " and $filterSql"; + $rangeSql .= $filterSql; + $eventsSql .= $filterSql; + } + + if ( !isset($minTime) || !isset($maxTime) ) + { + // Dynamically determine range + $row = dbFetchOne( $rangeSql ); + + if ( !isset($minTime) ) + $minTime = $row['MinTime']; + if ( !isset($maxTime) ) + $maxTime = $row['MaxTime']; + } + + if ( empty($minTime) ) + $minTime = $tempMinTime; + if ( empty($maxTime) ) + $maxTime = $tempMaxTime; + if ( empty($maxTime) ) + $maxTime = "now"; + + $minTimeT = strtotime($minTime); + $maxTimeT = strtotime($maxTime); + $range = ($maxTimeT - $minTimeT) + 1; + $halfRange = (int)($range/2); + $midTimeT = $minTimeT + $halfRange; + $midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT ); +} + +//echo "MnT: $tempMinTime, MxT: $tempMaxTime, ExP: $tempExpandable
"; +if ( $tree ) +{ + appendDatetimeRange( $tree, $minTime, $maxTime ); + + $filterQuery = parseTreeToQuery( $tree ); +} +else +{ + $filterQuery = false; +} + +$scales = array( + array( "name"=>"year", "factor"=>60*60*24*365, "align"=>1, "zoomout"=>2, "label"=>STRF_TL_AXIS_LABEL_YEAR ), + array( "name"=>"month", "factor"=>60*60*24*30, "align"=>1, "zoomout"=>12, "label"=>STRF_TL_AXIS_LABEL_MONTH ), + array( "name"=>"week", "factor"=>60*60*24*7, "align"=>1, "zoomout"=>4.25, "label"=>STRF_TL_AXIS_LABEL_WEEK, "labelCheck"=>"%W" ), + array( "name"=>"day", "factor"=>60*60*24, "align"=>1, "zoomout"=>7, "label"=>STRF_TL_AXIS_LABEL_DAY ), + array( "name"=>"hour4", "factor"=>60*60, "align"=>4, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_4HOUR, "labelCheck"=>"%H" ), + array( "name"=>"hour", "factor"=>60*60, "align"=>1, "zoomout"=>4, "label"=>STRF_TL_AXIS_LABEL_HOUR, "labelCheck"=>"%H" ), + array( "name"=>"minute10", "factor"=>60, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10MINUTE, "labelCheck"=>"%M" ), + array( "name"=>"minute", "factor"=>60, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_MINUTE, "labelCheck"=>"%M" ), + array( "name"=>"second10", "factor"=>1, "align"=>10, "zoomout"=>6, "label"=>STRF_TL_AXIS_LABEL_10SECOND ), + array( "name"=>"second", "factor"=>1, "align"=>1, "zoomout"=>10, "label"=>STRF_TL_AXIS_LABEL_SECOND ), +); + +$majXScale = getDateScale( $scales, $range, $chart['grid']['x']['major']['min'], $chart['grid']['x']['major']['max'] ); + +// Adjust the range etc for scale +$minTimeT -= $minTimeT%($majXScale['factor']*$majXScale['align']); +$minTime = strftime( STRF_FMT_DATETIME_DB, $minTimeT ); +$maxTimeT += (($majXScale['factor']*$majXScale['align'])-$maxTimeT%($majXScale['factor']*$majXScale['align']))-1; +if ( $maxTimeT > time() ) + $maxTimeT = time(); +$maxTime = strftime( STRF_FMT_DATETIME_DB, $maxTimeT ); +$range = ($maxTimeT - $minTimeT) + 1; +$halfRange = (int)($range/2); +$midTimeT = $minTimeT + $halfRange; +$midTime = strftime( STRF_FMT_DATETIME_DB, $midTimeT ); + +//echo "R:$range
"; +//echo "MnT:$minTime
"; +//echo "MnTt:$minTimeT
"; +//echo "MdT:$midTime
"; +//echo "MdTt:$midTimeT
"; +//echo "MxT:$maxTime
"; +//echo "MxTt:$maxTimeT
"; + +if ( isset($minTime) && isset($maxTime) ) +{ + $eventsSql .= " and E.EndTime >= '$minTime' and E.StartTime <= '$maxTime'"; +} + +$eventsSql .= " order by Id asc"; +//echo "ESQL: $eventsSql
"; + +$chart['data'] = array( + "x" => array( + "lo" => strtotime( $minTime ), + "hi" => strtotime( $maxTime ), + ), + "y" => array( + "lo" => 0, + "hi" => 0, + ) +); + +$chart['data']['x']['range'] = ($chart['data']['x']['hi'] - $chart['data']['x']['lo']) + 1; +$chart['data']['x']['density'] = $chart['data']['x']['range']/$chart['graph']['width']; + +$monEventSlots = array(); +$monFrameSlots = array(); +$monitorIds = array(); +foreach( dbFetchAll( $eventsSql ) as $event ) +{ + if ( !isset($monitorIds[$event['MonitorId']]) ) + $monitorIds[$event['MonitorId']] = true; + + if ( !isset($monEventSlots[$event['MonitorId']]) ) + $monEventSlots[$event['MonitorId']] = array(); + if ( !isset($monFrameSlots[$event['MonitorId']]) ) + $monFrameSlots[$event['MonitorId']] = array(); + + $currEventSlots = &$monEventSlots[$event['MonitorId']]; + $currFrameSlots = &$monFrameSlots[$event['MonitorId']]; + + $startTimeT = strtotime($event['StartTime']); + $startIndex = $rawStartIndex = (int)(($startTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + if ( $startIndex < 0 ) + $startIndex = 0; + + if ( isset($event['EndTime']) ) + $endTimeT = strtotime($event['EndTime']); + else + $endTimeT = time(); + $endIndex = $rawEndIndex = (int)(($endTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + + if ( $endIndex >= $chart['graph']['width'] ) + $endIndex = $chart['graph']['width'] - 1; + + for ( $i = $startIndex; $i <= $endIndex; $i++ ) + { + if ( !isset($currEventSlots[$i]) ) + { + if ( $rawStartIndex == $rawEndIndex ) + { + $offset = 1; + } + else + { + $offset = 1 + ($event['Frames']?((int)(($event['Frames']-1)*(($i-$rawStartIndex)/($rawEndIndex-$rawStartIndex)))):0); + } + $currEventSlots[$i] = array( "count"=>0, "width"=>1, "offset"=>$offset, "event"=>$event ); + } + else + { + $currEventSlots[$i]['count']++; + } + } + if ( $event['MaxScore'] > 0 ) + { + if ( $startIndex == $endIndex ) + { + $framesSql = "select FrameId,Score from Frames where EventId = '".$event['Id']."' and Score > 0 order by Score desc limit 1"; + $frame = dbFetchOne( $framesSql ); + + $i = $startIndex; + if ( !isset($currFrameSlots[$i]) ) + { + $currFrameSlots[$i] = array( "count"=>1, "value"=>$event['MaxScore'], "event"=>$event, "frame"=>$frame ); + } + else + { + $currFrameSlots[$i]['count']++; + if ( $event['MaxScore'] > $currFrameSlots[$i]['value'] ) + { + $currFrameSlots[$i]['value'] = $event['MaxScore']; + $currFrameSlots[$i]['event'] = $event; + $currFrameSlots[$i]['frame'] = $frame; + } + } + if ( $event['MaxScore'] > $chart['data']['y']['hi'] ) + { + $chart['data']['y']['hi'] = $event['MaxScore']; + } + } + else + { + $framesSql = "select FrameId,Delta,unix_timestamp(TimeStamp) as TimeT,Score from Frames where EventId = '".$event['Id']."' and Score > 0"; + $result = dbQuery( $framesSql ); + while( $frame = dbFetchNext( $result ) ) + { + if ( $frame['Score'] == 0 ) + continue; + $frameTimeT = $frame['TimeT']; + $frameTimeT = $startTimeT + $frame['Delta']; + $frameIndex = (int)(($frameTimeT - $chart['data']['x']['lo']) / $chart['data']['x']['density']); + if ( $frameIndex < 0 ) + continue; + if ( $frameIndex >= $chart['graph']['width'] ) + continue; + + if ( !isset($currFrameSlots[$frameIndex]) ) + { + $currFrameSlots[$frameIndex] = array( "count"=>1, "value"=>$frame['Score'], "event"=>$event, "frame"=>$frame ); + } + else + { + $currFrameSlots[$frameIndex]['count']++; + if ( $frame['Score'] > $currFrameSlots[$frameIndex]['value'] ) + { + $currFrameSlots[$frameIndex]['value'] = $frame['Score']; + $currFrameSlots[$frameIndex]['event'] = $event; + $currFrameSlots[$frameIndex]['frame'] = $frame; + } + } + if ( $frame['Score'] > $chart['data']['y']['hi'] ) + { + $chart['data']['y']['hi'] = $frame['Score']; + } + } + } + } +} + +ksort( $monitorIds, SORT_NUMERIC ); +ksort( $monEventSlots, SORT_NUMERIC ); +ksort( $monFrameSlots, SORT_NUMERIC ); + +// No longer needed? +if ( false ) +{ + // Add on missing frames + foreach( array_keys($monFrameSlots) as $monitorId ) + { + unset( $currFrameSlots ); + $currFrameSlots = &$monFrameSlots[$monitorId]; + for ( $i = 0; $i < $chart['graph']['width']; $i++ ) + { + if ( isset($currFrameSlots[$i]) ) + { + if ( !isset($currFrameSlots[$i]['frame']) ) + { + $framesSql = "select FrameId,Score from Frames where EventId = '".$currFrameSlots[$i]['event']['Id']."' and Score > 0 order by FrameId limit 1"; + $currFrameSlots[$i]['frame'] = dbFetchOne( $framesSql ); + } + } + } + } +} + +$chart['data']['y']['range'] = ($chart['data']['y']['hi'] - $chart['data']['y']['lo']) + 1; +$chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['height']; + +$majYScale = getYScale( $chart['data']['y']['range'], $chart['grid']['y']['major']['min'], $chart['grid']['y']['major']['max'] ); + +$maxWidth = 0; +$maxHeight = 0; + +foreach ( array_keys($monitorIds) as $monitorId ) +{ + if ( $maxWidth < $monitors[$monitorId]['Width'] ) + $maxWidth = $monitors[$monitorId]['Width']; + if ( $maxHeight < $monitors[$monitorId]['Height'] ) + $maxHeight = $monitors[$monitorId]['Height']; +} + +//print_r( $monEventSlots ); +// Optimise boxes +foreach( array_keys($monEventSlots) as $monitorId ) +{ + unset( $currEventSlots ); + $currEventSlots = &$monEventSlots[$monitorId]; + for ( $i = 0; $i < $chart['graph']['width']; $i++ ) + { + if ( isset($currEventSlots[$i]) ) + { + if ( isset($currSlot) ) + { + if ( $currSlot['event']['Id'] == $currEventSlots[$i]['event']['Id'] ) + { + if ( $currSlot['width'] < $maxEventWidth ) + { + // Merge slots for the same long event + $currSlot['width']++; + unset( $currEventSlots[$i] ); + continue; + } + elseif ( $currSlot['offset'] < $currEventSlots[$i]['offset'] ) + { + // Split very long events + $currEventSlots[$i]['frame'] = array( 'FrameId'=>$currEventSlots[$i]['offset'] ); + } + } + elseif ( $currSlot['width'] < $minEventWidth ) + { + // Merge multiple small events + $currSlot['width']++; + unset( $currEventSlots[$i] ); + continue; + } + } + $currSlot = &$currEventSlots[$i]; + } + else + { + unset( $currSlot ); + } + } + if ( isset( $currSlot ) ) + unset( $currSlot ); +} +//print_r( $monEventSlots ); + +// Stack events +$frameSlots = array(); +$frameMonitorIds = array_keys($monFrameSlots); +for ( $i = 0; $i < $chart['graph']['width']; $i++ ) +{ + foreach ( $frameMonitorIds as $frameMonitorId ) + { + unset( $currFrameSlots ); + $currFrameSlots = &$monFrameSlots[$frameMonitorId]; + if ( isset($currFrameSlots[$i]) ) + { + if ( !isset($frameSlots[$i]) ) + { + $frameSlots[$i] = array(); + $frameSlots[$i][] = &$currFrameSlots[$i]; + } + else + { + $slotCount = count($frameSlots[$i]); + for ( $j = 0; $j < $slotCount; $j++ ) + { + if ( $currFrameSlots[$i]['value'] > $frameSlots[$i][$j]['value'] ) + { + for ( $k = $slotCount; $k > $j; $k-- ) + { + $frameSlots[$i][$k] = $frameSlots[$i][$k-1]; + } + $frameSlots[$i][$j] = &$currFrameSlots[$i]; + break 2; + } + } + $frameSlots[$i][] = &$currFrameSlots[$i]; + } + } + } +} + +//print_r( $monEventSlots ); +//print_r( $monFrameSlots ); +//print_r( $chart ); + +$graphHeight = $chart['graph']['height']; + +if ( $mode == "overlay" ) +{ + $minEventBarHeight = 10; + $maxEventBarHeight = 40; + + if ( count($monitorIds) ) + { + $chart['graph']['eventBarHeight'] = $minEventBarHeight; + while ( ($chart['graph']['eventsHeight'] = (($chart['graph']['eventBarHeight'] * count($monitorIds)) + (count($monitorIds)-1))) < $maxEventBarHeight ) + { + $chart['graph']['eventBarHeight']++; + } + } + else + { + $chart['graph']['eventBarHeight'] = $maxEventBarHeight; + $chart['graph']['eventsHeight'] = $maxEventBarHeight; + } + $chart['graph']['activityHeight'] = ($graphHeight - $chart['graph']['eventsHeight']); + $chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityHeight']; + + $chart['eventBars'] = array(); + $top = $chart['graph']['activityHeight']; + foreach ( array_keys($monitorIds) as $monitorId ) + { + $chart['eventBars'][$monitorId] = array( 'top' => $top ); + $top += $chart['graph']['eventBarHeight']+1; + } +} +elseif ( $mode == "split" ) +{ + $minActivityBarHeight = 30; + $minEventBarHeight = 10; + $maxEventBarHeight = 40; + + if ( count($monitorIds) ) + { + $chart['graph']['eventBarHeight'] = $minEventBarHeight; + $chart['graph']['activityBarHeight'] = $minActivityBarHeight; + while ( ((($chart['graph']['eventBarHeight']+$chart['graph']['activityBarHeight']) * count($monitorIds)) + ((2*count($monitorIds))-1)) < $graphHeight ) + { + $chart['graph']['activityBarHeight']++; + if ( $chart['graph']['eventBarHeight'] < $maxEventBarHeight ) + { + $chart['graph']['eventBarHeight']++; + } + } + } + else + { + $chart['graph']['eventBarHeight'] = $maxEventBarHeight; + $chart['graph']['activityBarHeight'] = $graphHeight - $chart['graph']['eventBarHeight']; + } + $chart['data']['y']['density'] = $chart['data']['y']['range']/$chart['graph']['activityBarHeight']; + +?> + $top ); + $chart['eventBars'][$monitorId] = array( 'top' => $top+$chart['graph']['activityBarHeight']+1 ); + $top += $chart['graph']['activityBarHeight']+1+$chart['graph']['eventBarHeight']+1; + } +} + +preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $minTime, $startMatches ); +preg_match( '/^(\d+)-(\d+)-(\d+) (\d+):(\d+)/', $maxTime, $endMatches ); + +if ( $startMatches[1] != $endMatches[1] ) +{ + // Different years + $title = strftime( STRF_TL_AXIS_RANGE_YEAR1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_YEAR2, $chart['data']['x']['hi'] ); +} +elseif ( $startMatches[2] != $endMatches[2] ) +{ + // Different months + $title = strftime( STRF_TL_AXIS_RANGE_MONTH1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_MONTH2, $chart['data']['x']['hi'] ); +} +elseif ( $startMatches[3] != $endMatches[3] ) +{ + // Different dates + $title = strftime( STRF_TL_AXIS_RANGE_DAY1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_DAY2, $chart['data']['x']['hi'] ); +} +else +{ + // Different times + $title = strftime( STRF_TL_AXIS_RANGE_TIME1, $chart['data']['x']['lo'] )." - ".strftime( STRF_TL_AXIS_RANGE_TIME2, $chart['data']['x']['hi'] ); +} + +function drawXGrid( $chart, $scale, $labelClass, $tickClass, $gridClass, $zoomClass=false ) +{ + global $SLANG; + + ob_start(); + $labelCount = 0; + $lastTick = 0; + unset( $lastLabel ); + $labelCheck = isset($scale['labelCheck'])?$scale['labelCheck']:$scale['label']; +?> +
+ 1 ) + { + $label = (int)(strftime( $labelCheck, $timeOffset )/$scale['align']); + } + else + { + $label = strftime( $labelCheck, $timeOffset ); + } + if ( !isset($lastLabel) || ($lastLabel != $label) ) + { + $labelCount++; + } + if ( $labelCount >= $scale['divisor'] ) + { + $labelCount = 0; + if ( isset($lastLabel) ) + { + if ( $labelClass ) + { +?> +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ +
+
+
+
<?= $SLANG['ViewEvent'] ?>
+
+
+
+
+

Pass your mouse over the graph to view a snapshot image and event details.

+

Click on the coloured sections of the graph, or the image, to view the event.

+

Click on the background to zoom in to a smaller time period based around your click.

+

Use the controls below to zoom out or navigate back and forward through the time range.

+
+
+
+
+ +
+
+
+
+ +
+$slots ) + { + foreach ( $slots as $slot ) + { + $slotHeight = (int)($slot['value']/$chart['data']['y']['density']); + + if ( $slotHeight <= 0 ) + continue; + + if ( $mouseover ) + { + $behaviours = array( + 'onclick="'.getSlotShowEventBehaviour( $slot ).'"', + 'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"' + ); + } + else + { + $behaviours = array( + 'onclick="'.getSlotPreviewEventBehaviour( $slot ).'"' + ); + } +?> +
>
+ +
+ +
+$slot ) + { + $slotHeight = (int)($slot['value']/$chart['data']['y']['density']); + + if ( $slotHeight <= 0 ) + continue; + + if ( $mouseover ) + { + $behaviours = array( + 'onclick="'.getSlotShowEventBehaviour( $slot ).'"', + 'onmouseover="'.getSlotPreviewEventBehaviour( $slot ).'"' + ); + } + else + { + $behaviours = array( + 'onclick="'.getSlotPreviewEventBehaviour( $slot ).'"' + ); + } + ?> +
>
+ +
+ +
+ +
>
+ +
+ +
+
+
+
+ + <?= $monitors[$monitorId]['Name'] ?> + +
+
+
+
+
+ + diff --git a/web/skins/classic/views/user.php b/web/skins/classic/views/user.php new file mode 100644 index 000000000..55c7d9514 --- /dev/null +++ b/web/skins/classic/views/user.php @@ -0,0 +1,154 @@ +$SLANG['No'], 1=>$SLANG['Yes'] ); +$nv = array( 'None'=>$SLANG['None'], 'View'=>$SLANG['View'] ); +$nve = array( 'None'=>$SLANG['None'], 'View'=>$SLANG['View'], 'Edit'=>$SLANG['Edit'] ); +$bandwidths = array_merge( array( ""=>"" ), $bwArray ); +$langs = array_merge( array( ""=>"" ), getLanguages() ); + +$sql = "select Id,Name from Monitors order by Sequence asc"; +$monitors = array(); +foreach( dbFetchAll( $sql ) as $monitor ) +{ + $monitors[] = $monitor; +} + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['User']." - ".$newUser['Username'] ); +?> + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+
+
+
+ + diff --git a/web/skins/classic/views/version.php b/web/skins/classic/views/version.php new file mode 100644 index 000000000..2feacbbbe --- /dev/null +++ b/web/skins/classic/views/version.php @@ -0,0 +1,93 @@ + $SLANG['GoToZoneMinder'] +); + +if ( verNum( ZM_DYN_CURR_VERSION ) != verNum( ZM_DYN_LAST_VERSION ) ) +{ + $options = array_merge( $options, array( + "ignore" => $SLANG['VersionIgnore'], + "hour" => $SLANG['VersionRemindHour'], + "day" => $SLANG['VersionRemindDay'], + "week" => $SLANG['VersionRemindWeek'], + "never" => $SLANG['VersionRemindNever'] + ) ); +} + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Version'] ); +?> + +
+ +
+ +

+

+
+ +
+ +

+

+

+
+ +
+ +
+ + +

+

+

+
+ + +
+
+ +
+
+ + diff --git a/web/skins/classic/views/video.php b/web/skins/classic/views/video.php new file mode 100644 index 000000000..a34037aea --- /dev/null +++ b/web/skins/classic/views/video.php @@ -0,0 +1,241 @@ + + +
+ +
+ +

+
+ +
+ + + + + + + + + + + + + + + + + + + + +
checked="checked"/>
+ disabled="disabled"/> +
+ +

+ + + +

+ +

+ + + + + + + + + + + + + 0 ) + { + preg_match( '/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches ); + if ( preg_match( '/^r(.+)$/', $matches[2], $temp_matches ) ) + { + $rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) ); + $rateText = isset($rates[$rate])?$rates[$rate]:($rate."x"); + } + elseif ( preg_match( '/^F(.+)$/', $matches[2], $temp_matches ) ) + { + $rateText = $temp_matches[1]."fps"; + } + if ( preg_match( '/^s(.+)$/', $matches[3], $temp_matches ) ) + { + $scale = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) ); + $scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x"); + } + elseif ( preg_match( '/^S(.+)$/', $matches[3], $temp_matches ) ) + { + $scaleText = $temp_matches[1]; + } + $width = $scale?reScale( $event['Width'], $scale ):$event['Width']; + $height = $scale?reScale( $event['Height'], $scale ):$event['Height']; +?> + + + + + + + + + +
 /  / 
+ +
+
+ + diff --git a/web/skins/classic/views/watch.php b/web/skins/classic/views/watch.php new file mode 100644 index 000000000..661630ab3 --- /dev/null +++ b/web/skins/classic/views/watch.php @@ -0,0 +1,230 @@ + + +
+
+ +
+ +
+
+ +
+ +
+ +
 -  fps
+
+ + + +
+ +
+ + + + + +
+
+ + diff --git a/web/skins/classic/views/zone.php b/web/skins/classic/views/zone.php new file mode 100644 index 000000000..80a3f5e0e --- /dev/null +++ b/web/skins/classic/views/zone.php @@ -0,0 +1,288 @@ + 0 ) + { + $zone = dbFetchOne( "select * from Zones where MonitorId = '".dbEscape($monitor['Id'])."' and Id = '".dbEscape($zid)."'" ); + } + else + { + $zone = array( + 'Name' => $SLANG['New'], + 'Id' => 0, + 'MonitorId' => $monitor['Id'], + 'NumCoords' => 4, + 'Coords' => sprintf( "%d,%d %d,%d, %d,%d %d,%d", $minX, $minY, $maxX, $minY, $maxX, $maxY, $minX, $maxY ), + 'Area' => $monitor['Width'] * $monitor['Height'], + 'AlarmRGB' => 0xff0000, + 'CheckMethod' => 'Blobs', + 'MinPixelThreshold' => '', + 'MaxPixelThreshold' => '', + 'MinAlarmPixels' => '', + 'MaxAlarmPixels' => '', + 'FilterX' => '', + 'FilterY' => '', + 'MinFilterPixels' => '', + 'MaxFilterPixels' => '', + 'MinBlobPixels' => '', + 'MaxBlobPixels' => '', + 'MinBlobs' => '', + 'MaxBlobs' => '', + 'OverloadFrames' => '', + ); + } + $zone['Points'] = coordsToPoints( $zone['Coords'] ); + + $newZone = $zone; +} + +//if ( !$points ) +//{ + //$points = $zone['Points']; +//} + +ksort( $newZone['Points'], SORT_NUMERIC ); + +$newZone['Coords'] = pointsToCoords( $newZone['Points'] ); +$newZone['Area'] = getPolyArea( $newZone['Points'] ); +$selfIntersecting = isSelfIntersecting( $newZone['Points'] ); + +$wd = getcwd(); +chdir( ZM_DIR_IMAGES ); +$command = getZmuCommand( " -m ".$mid." -z" ); +$command .= '"'.$zid.' '.$hicolor.' '.$newZone['Coords'].'"'; +$status = exec( escapeshellcmd( $command ) ); +chdir( $wd ); + +$zoneImage = ZM_DIR_IMAGES.'/Zones'.$monitor['Id'].'.jpg?'.time(); + +$focusWindow = true; + +xhtmlHeaders(__FILE__, $SLANG['Zone'] ); +?> + +
+ +
+
+ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"applyPreset()", "onblur"=>"this.selectedIndex=0" ) ) ?>
 /  / 
+$pl
"; + } +} +?> +
+
+
+
+
+ Zone Image +
+
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
disabled="disabled"/> disabled="disabled"/>+ 3 ) { ?>  X
+
 
+ disabled="disabled"/> +
+
+
+
+ + diff --git a/web/skins/classic/views/zones.php b/web/skins/classic/views/zones.php new file mode 100644 index 000000000..3089c9ad3 --- /dev/null +++ b/web/skins/classic/views/zones.php @@ -0,0 +1,106 @@ + + +
+ +
+ + + <?= htmlspecialchars($zone['Name']) ?> + + + + zones +
+ + + + + + + + + + + + + + + + + + + + + + +
 /  disabled="disabled"/>
+
+ disabled="disabled"/> + +
+
+
+
+ + diff --git a/web/skins/mobile/Makefile.am b/web/skins/mobile/Makefile.am new file mode 100644 index 000000000..35051fade --- /dev/null +++ b/web/skins/mobile/Makefile.am @@ -0,0 +1,14 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile + +SUBDIRS = \ + ajax \ + css \ + graphics \ + includes \ + lang \ + views + +dist_web_DATA = \ + skin.php diff --git a/web/skins/mobile/Makefile.in b/web/skins/mobile/Makefile.in new file mode 100644 index 000000000..f5eeebb17 --- /dev/null +++ b/web/skins/mobile/Makefile.in @@ -0,0 +1,660 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile +SUBDIRS = \ + ajax \ + css \ + graphics \ + includes \ + lang \ + views + +dist_web_DATA = \ + skin.php + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dist_webDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/ajax/Makefile.am b/web/skins/mobile/ajax/Makefile.am new file mode 100644 index 000000000..0558929c0 --- /dev/null +++ b/web/skins/mobile/ajax/Makefile.am @@ -0,0 +1,5 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/ajax + +dist_web_DATA = # No files here diff --git a/web/skins/mobile/ajax/Makefile.in b/web/skins/mobile/ajax/Makefile.in new file mode 100644 index 000000000..d7dbdd679 --- /dev/null +++ b/web/skins/mobile/ajax/Makefile.in @@ -0,0 +1,451 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/ajax +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/ajax +dist_web_DATA = # No files here +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/ajax/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/ajax/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/css/Makefile.am b/web/skins/mobile/css/Makefile.am new file mode 100644 index 000000000..6353e163e --- /dev/null +++ b/web/skins/mobile/css/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/css + +dist_web_DATA = \ + skin.css diff --git a/web/skins/mobile/css/Makefile.in b/web/skins/mobile/css/Makefile.in new file mode 100644 index 000000000..eb3d9ffc2 --- /dev/null +++ b/web/skins/mobile/css/Makefile.in @@ -0,0 +1,453 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/css +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/css +dist_web_DATA = \ + skin.css + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/css/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/css/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/css/skin.css b/web/skins/mobile/css/skin.css new file mode 100644 index 000000000..b996392a3 --- /dev/null +++ b/web/skins/mobile/css/skin.css @@ -0,0 +1,311 @@ +/* + * Primary look and feel styles + */ + +body { + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 100%; + color: #333333; + font-weight: normal; + text-align: center; +} + +h1 { + font-family: inherit; + font-size: 120%; + color: #000066; + font-weight: bold; +} + +h2 { + font-family: inherit; + font-size: 110%; + color: #000066; + font-weight: bold; +} + +h3 { + font-family: inherit; + font-size: 100%; + color: #016A9D; + font-weight: bold; +} + +p { + font-family: inherit; + font-size: 100%; + color: #333333; + font-weight: normal; +} + +th { + font-weight: bold; + color: #016A9D; +} + +a:link { + color: #7F7FB2; + text-decoration: none; +} + +a:visited { + color: #7F7FB2; + text-decoration: none; +} + +a:hover { + color: #666699; + text-decoration: underline; +} + +label { + margin-right: 4px; +} + +input,textarea,select { + border: 1px #7F7FB2 solid; + font-family: inherit; + font-size: 100%; + color: #333333; +} + +input[type=text], input[type=password], textarea { + padding: 1px; +} + +input.noborder { + border: 0; +} + +input[disabled] { + color: #888888; +} + +img.normal { + border: white solid 1px; +} + +img.alarm { + border: red solid 1px; +} + +hr { + height: 1px; + width: 100%; + border: 0; + color: #7f7fb2; + background-color: #7f7fb2; +} + +/* + * Major league table for multiple inputs or presentation + */ + +#content table.major { + margin: 4px auto; + width: 100%; + border-collapse: collapse; +} + +#content table.major tr.highlight { + background-color: #eeeeee; +} + +#content table.major thead tr th { + padding-top: 6px; + padding-bottom: 6px; + vertical-align: middle; +} + +#content table.major tfoot td { + padding-top: 6px; + padding-bottom: 6px; + vertical-align: middle; +} + +#content table.major th, #content table.major td { + border: 1px solid #7f7fb2; + padding: 3px; + text-align: left; +} + +#content table.major th { + vertical-align: bottom; +} + +#content table.major td { + vertical-align: middle; +} + +#content table.major th[scope=row] { + padding: 4px 3px 3px; + vertical-align: top; + text-align: right; +} + +#content table.major .colMark, #content table.major .colSelect { + text-align: center; +} +/* + * Lesser table for very simple forms + */ + +#content table.minor { + width: 200px; + margin: 0 auto; +} + +#content table.minor td { + padding: 4px; +} + +#content table.minor .colLeft { + width: 50%; + text-align: right; +} + +#content table.minor .colRight { + width: 50%; + text-align: left; +} + +#content table.minor input[type=submit] +{ + margin-top: 4px; + padding: 0 2px; + font-size: 120%; +} + +/* + * Behavior classes + */ +.error { + /*font-family: Verdana, Arial, Helvetica, sans-serif;*/ + font-size: 100%; + color: #DC143C; + font-weight: bold; +} + +.warn { + /*font-family: Verdana, Arial, Helvetica, sans-serif;*/ + font-size: 100%; + color: #FF8C00; + font-weight: bold; +} + +.info { + /*font-family: Verdana, Arial, Helvetica, sans-serif;*/ + font-size: 100%; + color: #688E23; + font-weight: bold; +} + +.errorText { + color: #DC143C; +} + +.warnText { + color: #FF8C00; +} + +.infoText { + color: #688E23; +} + +.disabledText { + font-style: italic; +} + +/* + * Generic useful classes, especially with mootools + */ + +.hidden { + display: none; +} + +.invisible { + visibility: hidden; +} + +.nowrap { + white-space: nowrap; +} + +div.clear { + clear: both; +} + +/* + * Primary layout styles + */ + +#page { + width: 100%; +} + +#header { + width: 98%; + line-height: 24px; + margin: 4px auto 0; + clear: both; +} + +#header h2 { + left: 0; +} + +#headerControl { +} + +#headerButtons { + float: right; +} + +#headerButtons a { + margin-left: 8px; +} + +#content { + width: 98%; + margin: 4px auto; + line-height: 130%; + text-align: center; + clear: both; +} + +#contentTable { + width: 100%; +} + +#content p { + margin-top: 4px; +} + +#content p.textblock { + text-align: justify; + padding: 4px; +} + +#content > input[type=submit], #content > input[type=button] { + margin-top: 4px; +} + +#content table input[type=submit], #content table input[type=button] { + margin-top: 0; +} + +#contentButtons { + margin: 4px auto 0; +} + +#contentButtons input, #contentButtons a { + margin: 0 4px; +} + +#footer { + width: 98%; + margin: 4px auto 0; + clear: both; +} + diff --git a/web/skins/mobile/graphics/Makefile.am b/web/skins/mobile/graphics/Makefile.am new file mode 100644 index 000000000..dfd43bef7 --- /dev/null +++ b/web/skins/mobile/graphics/Makefile.am @@ -0,0 +1,5 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/graphics + +dist_web_DATA = # No files here diff --git a/web/skins/mobile/graphics/Makefile.in b/web/skins/mobile/graphics/Makefile.in new file mode 100644 index 000000000..6de8e67b6 --- /dev/null +++ b/web/skins/mobile/graphics/Makefile.in @@ -0,0 +1,451 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/graphics +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/graphics +dist_web_DATA = # No files here +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/graphics/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/graphics/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/includes/Makefile.am b/web/skins/mobile/includes/Makefile.am new file mode 100644 index 000000000..c88ad435a --- /dev/null +++ b/web/skins/mobile/includes/Makefile.am @@ -0,0 +1,9 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/includes + +dist_web_DATA = \ + init.php \ + config.php \ + functions.php \ + control_functions.php diff --git a/web/skins/mobile/includes/Makefile.in b/web/skins/mobile/includes/Makefile.in new file mode 100644 index 000000000..cf5b6a84e --- /dev/null +++ b/web/skins/mobile/includes/Makefile.in @@ -0,0 +1,456 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/includes +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/includes +dist_web_DATA = \ + init.php \ + config.php \ + functions.php \ + control_functions.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/includes/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/includes/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/includes/config.php b/web/skins/mobile/includes/config.php new file mode 100644 index 000000000..956c36bcc --- /dev/null +++ b/web/skins/mobile/includes/config.php @@ -0,0 +1,63 @@ + "50x", + "2000" => "20x", + "500" => "5x", + "200" => "2x", + "100" => $SLANG['Real'], + "50" => "1/2x", +); + +$scales = array( + "400" => "4x", + "300" => "3x", + "200" => "2x", + "150" => "1.5x", + "100" => $SLANG['Actual'], + "75" => "3/4x", + "50" => "1/2x", + "33" => "1/3x", + "25" => "1/4x", +); + +switch ( $_COOKIE['zmBandwidth'] ) +{ + case "phone" : // Very incomplete at present + { + define( "ZM_WEB_CAN_STREAM", ZM_WEB_P_CAN_STREAM ); // Override the automatic detection of browser streaming capability + define( "ZM_WEB_STREAM_METHOD", ZM_WEB_P_STREAM_METHOD ); // Which method should be used to send video streams to your brow + define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_P_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%) + define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_P_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%) + define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_P_VIDEO_BITRATE ); // What the bitrate of any streamed video should be + define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_P_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be + define( "ZM_WEB_SCALE_THUMBS", ZM_WEB_P_SCALE_THUMBS ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling + define( "ZM_WEB_AJAX_TIMEOUT", ZM_WEB_P_AJAX_TIMEOUT ); // Timeout to use for Ajax requests, no timeout used if unset + + break; + } +} + +?> diff --git a/web/skins/mobile/includes/control_functions.php b/web/skins/mobile/includes/control_functions.php new file mode 100644 index 000000000..3a5314998 --- /dev/null +++ b/web/skins/mobile/includes/control_functions.php @@ -0,0 +1,186 @@ + +
+
+
+ +
+ + " name="preset" value=""/> + +
+
+
+
+ diff --git a/web/skins/mobile/includes/functions.php b/web/skins/mobile/includes/functions.php new file mode 100644 index 000000000..40c1b055a --- /dev/null +++ b/web/skins/mobile/includes/functions.php @@ -0,0 +1,66 @@ +'."\n" ); +?> + + + + <?= ZM_WEB_TITLE_PREFIX ?> - <?= $title ?> + + + + + + + + + + + diff --git a/web/skins/mobile/includes/init.php b/web/skins/mobile/includes/init.php new file mode 100644 index 000000000..ae92bcdee --- /dev/null +++ b/web/skins/mobile/includes/init.php @@ -0,0 +1,29 @@ + diff --git a/web/skins/mobile/lang/Makefile.am b/web/skins/mobile/lang/Makefile.am new file mode 100644 index 000000000..5084203fb --- /dev/null +++ b/web/skins/mobile/lang/Makefile.am @@ -0,0 +1,5 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/lang + +dist_web_DATA = # No files here diff --git a/web/skins/mobile/lang/Makefile.in b/web/skins/mobile/lang/Makefile.in new file mode 100644 index 000000000..2663443d2 --- /dev/null +++ b/web/skins/mobile/lang/Makefile.in @@ -0,0 +1,451 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/lang +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/lang +dist_web_DATA = # No files here +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/lang/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/lang/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/skin.php b/web/skins/mobile/skin.php new file mode 100644 index 000000000..0b7f59747 --- /dev/null +++ b/web/skins/mobile/skin.php @@ -0,0 +1,104 @@ +GetDeviceCapabilitiesFromAgent($_SERVER['HTTP_USER_AGENT']); + + //print_r( $wurfl->wurfl_agent ); + if ( $wurfl->wurfl_agent ) + { + if ( $wurfl->getDeviceCapability( 'html_wi_oma_xhtmlmp_1_0' ) ) + { + $device['width'] = $wurfl->getDeviceCapability( 'resolution_width' ); + $device['height'] = $wurfl->getDeviceCapability( 'resolution_height' ); + } + } +} +else +{ + // This is an example of using fixed device strings to just match your phone etc + $devices = array( + array( 'name'=>"Motorola V600", 'ua_match'=>"MOT-V600", 'skin'=>"mobile", 'cookies'=>false, 'width'=>176, 'height'=>220 ), + ); + + foreach ( $devices as $tempDevice ) + { + if ( preg_match( '/'.$tempDevice['ua_match'].'/', $_SERVER['HTTP_USER_AGENT'] ) ) + { + $skin = $tempDevice['skin']; + $cookies = $tempDevice['cookies']; + break; + } + } +} + +foreach ( getSkinIncludes( 'includes/config.php' ) as $includeFile ) + require_once $includeFile; + +foreach ( getSkinIncludes( 'includes/functions.php' ) as $includeFile ) + require_once $includeFile; + +if ( empty($view) ) + $view = isset($user)?'console':'login'; + +if ( !isset($user) && ZM_OPT_USE_AUTH ) +{ + if ( ZM_AUTH_TYPE == "remote" && !empty( $_SERVER['REMOTE_USER'] ) ) + { + $view = "postlogin"; + $action = "login"; + $_REQUEST['username'] = $_SERVER['REMOTE_USER']; + } + else + { + $view = "login"; + } +} + +// If there are additional actions +foreach ( getSkinIncludes( 'includes/actions.php' ) as $includeFile ) + require_once $includeFile; + +?> diff --git a/web/skins/mobile/views/Makefile.am b/web/skins/mobile/views/Makefile.am new file mode 100644 index 000000000..c7d175ca3 --- /dev/null +++ b/web/skins/mobile/views/Makefile.am @@ -0,0 +1,22 @@ +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = \ + css + +webdir = @WEB_PREFIX@/skins/mobile/views + +dist_web_DATA = \ + console.php \ + devices.php \ + error.php \ + eventdetails.php \ + event.php \ + events.php \ + filter.php \ + frame.php \ + function.php \ + login.php \ + montage.php \ + state.php \ + video.php \ + watch.php diff --git a/web/skins/mobile/views/Makefile.in b/web/skins/mobile/views/Makefile.in new file mode 100644 index 000000000..9b2d72ee1 --- /dev/null +++ b/web/skins/mobile/views/Makefile.in @@ -0,0 +1,668 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/views +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = \ + css + +webdir = @WEB_PREFIX@/skins/mobile/views +dist_web_DATA = \ + console.php \ + devices.php \ + error.php \ + eventdetails.php \ + event.php \ + events.php \ + filter.php \ + frame.php \ + function.php \ + login.php \ + montage.php \ + state.php \ + video.php \ + watch.php + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/views/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/views/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dist_webDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/views/console.php b/web/skins/mobile/views/console.php new file mode 100644 index 000000000..9422c5d62 --- /dev/null +++ b/web/skins/mobile/views/console.php @@ -0,0 +1,178 @@ + array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "-1 hour" ), + ) + ), + ), + // Today + array( + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "today" ), + ) + ), + ), +); + +$running = daemonCheck(); +$status = $running?$SLANG['Running']:$SLANG['Stopped']; + +if ( $group = dbFetchOne( "select * from Groups where Name = 'Mobile'" ) ) + $groupIds = array_flip(explode( ',', $group['MonitorIds'] )); + +$maxWidth = 0; +$maxHeight = 0; +$cycleCount = 0; +$monitors = dbFetchAll( "select * from Monitors order by Sequence asc" ); +for ( $i = 0; $i < count($monitors); $i++ ) +{ + if ( !visibleMonitor( $monitors[$i]['Id'] ) ) + { + continue; + } + if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) ) + { + continue; + } + $monitors[$i]['Show'] = true; + $monitors[$i]['zmc'] = zmcStatus( $monitors[$i] ); + $monitors[$i]['zma'] = zmaStatus( $monitors[$i] ); + $counts = array(); + for ( $j = 0; $j < count($eventCounts); $j++ ) + { + $filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( "cnj" => "and", "attr" => "MonitorId", "op" => "=", "val" => $monitors[$i]['Id'] ) ); + parseFilter( $filter, false, '&' ); + $counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j"; + $monitors[$i]['eventCounts'][$j]['filter'] = $filter; + } + $sql = "select ".join($counts,", ")." from Events as E where MonitorId = '".$monitors[$i]['Id']."'"; + $counts = dbFetchOne( $sql ); + if ( $monitors[$i]['Function'] != 'None' ) + { + $cycleCount++; + if ( $maxWidth < $monitors[$i]['Width'] ) $maxWidth = $monitors[$i]['Width']; + if ( $maxHeight < $monitors[$i]['Height'] ) $maxHeight = $monitors[$i]['Height']; + } + $monitors[$i] = array_merge( $monitors[$i], $counts ); +} + +xhtmlHeaders( __FILE__, $SLANG['Console'] ); +?> + +
+ +
+ + + + + + + + + + + + + + + + + 1 ) { +?> + + + + + + + +
".substr( $monitor['Function'], 0, 4 )."", canEdit( 'Monitors' ) ) ?>
  
+
+
+ + diff --git a/web/skins/mobile/views/css/Makefile.am b/web/skins/mobile/views/css/Makefile.am new file mode 100644 index 000000000..86e0ff0a3 --- /dev/null +++ b/web/skins/mobile/views/css/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/mobile/views/css + +dist_web_DATA = \ + console.css diff --git a/web/skins/mobile/views/css/Makefile.in b/web/skins/mobile/views/css/Makefile.in new file mode 100644 index 000000000..06bd7f268 --- /dev/null +++ b/web/skins/mobile/views/css/Makefile.in @@ -0,0 +1,453 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/mobile/views/css +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/mobile/views/css +dist_web_DATA = \ + console.css + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/mobile/views/css/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/mobile/views/css/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/mobile/views/css/console.css b/web/skins/mobile/views/css/console.css new file mode 100644 index 000000000..49c711039 --- /dev/null +++ b/web/skins/mobile/views/css/console.css @@ -0,0 +1,16 @@ +#systemTime { + float: left; +} + +#systemState { + margin: 0 auto; + text-align: center; +} + +#systemStats { + float: right; +} + +td.colEvents { + text-align: right; +} diff --git a/web/skins/mobile/views/devices.php b/web/skins/mobile/views/devices.php new file mode 100644 index 000000000..1270e518d --- /dev/null +++ b/web/skins/mobile/views/devices.php @@ -0,0 +1,73 @@ + + +
+ +
+ + + + + + + + +
+

+
+
+ + diff --git a/web/skins/mobile/views/error.php b/web/skins/mobile/views/error.php new file mode 100644 index 000000000..0adf4f9f3 --- /dev/null +++ b/web/skins/mobile/views/error.php @@ -0,0 +1,34 @@ + + +
+ +
+

+

+
+
+ + diff --git a/web/skins/mobile/views/event.php b/web/skins/mobile/views/event.php new file mode 100644 index 000000000..b804c137c --- /dev/null +++ b/web/skins/mobile/views/event.php @@ -0,0 +1,143 @@ +=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn ".($sortOrder=='asc'?'desc':'asc'); +$result = dbQuery( $sql ); +while ( $row = dbFetchNext( $result ) ) +{ + if ( $row['Id'] == $_REQUEST['eid'] ) + { + $prevEvent = dbFetchNext( $result ); + break; + } +} + +$sql = "select E.* from Events as E inner join Monitors as M on E.MonitorId = M.Id where $sortColumn ".($sortOrder=='asc'?'>=':'<=')." '".$event[$_REQUEST['sort_field']]."'".$_REQUEST['filter']['sql'].$midSql." order by $sortColumn $sortOrder"; +$result = dbQuery( $sql ); +while ( $row = dbFetchNext( $result ) ) +{ + if ( $row['Id'] == $_REQUEST['eid'] ) + { + $nextEvent = dbFetchNext( $result ); + break; + } +} + +$framesPerPage = 15; +$framesPerLine = 3; +$maxShortcuts = 3; + +$paged = $event['Frames'] > $framesPerPage; + +if ( $paged && !empty($_REQUEST['page']) ) +{ + $loFrameId = (($_REQUEST['page']-1)*$framesPerPage)+1; + $hiFrameId = min( $_REQUEST['page']*$framesPerPage, $event['Frames'] ); +} +else +{ + $loFrameId = 1; + $hiFrameId = $event['Frames']; +} + +$sql = "select * from Frames where EventID = '".dbEscape($_REQUEST['eid'])."'"; +if ( $paged && !empty($_REQUEST['page']) ) + $sql .= " and FrameId between $loFrameId and $hiFrameId"; +$sql .= " order by FrameId"; +$frames = dbFetchAll( $sql ); + +$scale = getDeviceScale( $event['Width'], $event['Height'], $framesPerLine+0.3 ); + +$pages = (int)ceil($event['Frames']/$framesPerPage); +if ( !empty($_REQUEST['fid']) ) + $_REQUEST['page'] = ($_REQUEST['fid']/$framesPerPage)+1; + +$pagination = getPagination( $pages, $_REQUEST['page'], $maxShortcuts, '&eid='.$_REQUEST['eid'].$filterQuery.$sortQuery, '&' ); + +xhtmlHeaders( __FILE__, $SLANG['Event'].' - '.$event['Name'] ); +?> + +
+ +
+ +

+ +
+ + <?= $frame['Type'] ?>/<?= $frame['Type']=='Alarm'?$frame['Score']:0 ?> + +
+
+
+ + diff --git a/web/skins/mobile/views/eventdetails.php b/web/skins/mobile/views/eventdetails.php new file mode 100644 index 000000000..89a8acc73 --- /dev/null +++ b/web/skins/mobile/views/eventdetails.php @@ -0,0 +1,86 @@ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
s
()
//
+
+ 1 + <?= $frame['FrameId'] ?> +
+
+ + +
+
+
+ + diff --git a/web/skins/mobile/views/events.php b/web/skins/mobile/views/events.php new file mode 100644 index 000000000..dbe16b086 --- /dev/null +++ b/web/skins/mobile/views/events.php @@ -0,0 +1,157 @@ +$deviceLines)?$deviceLines:$limitLeft; + } + $eventsSql .= " limit $limitStart, $limitAmount"; +} +elseif ( !empty( $_REQUEST['limit'] ) ) +{ + $eventsSql .= " limit 0, ".$_REQUEST['limit']; +} + +$nEvents = dbFetchOne( $countSql, 'EventCount' ); +if ( !empty($limit) && $nEvents > $_REQUEST['limit'] ) +{ + $nEvents = $_REQUEST['limit']; +} +$pages = (int)ceil($nEvents/$deviceLines); + +$maxShortcuts = 3; +$pagination = getPagination( $pages, $_REQUEST['page'], $maxShortcuts, $filterQuery.$sortQuery.'&limit='.$_REQUEST['limit'], '&' ); + +xhtmlHeaders( __FILE__, $SLANG['Events'] ); +?> + +
+ +
+ +

+ + + + + + + + + + + + + + + + + + + +
+

+
+
+ + diff --git a/web/skins/mobile/views/filter.php b/web/skins/mobile/views/filter.php new file mode 100644 index 000000000..d01249109 --- /dev/null +++ b/web/skins/mobile/views/filter.php @@ -0,0 +1,71 @@ + + +
+ +
+
+ + 0 ) +{ +?> +
+ +
+
+ +
+ +

+ +
+
+
+ + diff --git a/web/skins/mobile/views/frame.php b/web/skins/mobile/views/frame.php new file mode 100644 index 000000000..403fe5201 --- /dev/null +++ b/web/skins/mobile/views/frame.php @@ -0,0 +1,73 @@ + + +
+ +
+ "> +
+ 1 ) { ?> + << + 1 ) { ?> + < + + > + + >> + +
+
+
+ + diff --git a/web/skins/mobile/views/function.php b/web/skins/mobile/views/function.php new file mode 100644 index 000000000..8825129ff --- /dev/null +++ b/web/skins/mobile/views/function.php @@ -0,0 +1,66 @@ + + +
+ +
+
+ +
+ +
+
+ checked="checked"/> +
+
+ +
+
+
+
+ + diff --git a/web/skins/mobile/views/login.php b/web/skins/mobile/views/login.php new file mode 100644 index 000000000..7882ce9be --- /dev/null +++ b/web/skins/mobile/views/login.php @@ -0,0 +1,54 @@ + + +
+ +
+
+ + + + + + + + + + +
" size="12"/>
+
+ +
+
+
+
+ + diff --git a/web/skins/mobile/views/montage.php b/web/skins/mobile/views/montage.php new file mode 100644 index 000000000..a491804e6 --- /dev/null +++ b/web/skins/mobile/views/montage.php @@ -0,0 +1,75 @@ + + +
+ +
+
+ + <?= $monitor['Name'] ?> + +
+
+
+
+ + diff --git a/web/skins/mobile/views/state.php b/web/skins/mobile/views/state.php new file mode 100644 index 000000000..caa7f8f74 --- /dev/null +++ b/web/skins/mobile/views/state.php @@ -0,0 +1,77 @@ + + +
+ +
+
+ + +
+ +
+
+
+
+ + diff --git a/web/skins/mobile/views/video.php b/web/skins/mobile/views/video.php new file mode 100644 index 000000000..46a2f1c80 --- /dev/null +++ b/web/skins/mobile/views/video.php @@ -0,0 +1,226 @@ += 352 && $deviceHeight >= 288 ) + $videoSize = "352x288"; +elseif ( $deviceWidth >= 176 && $deviceHeight >= 144 ) + $videoSize = "176x144"; +else + $videoSize = "128x96"; + +$eventWidth = $event['Width']; +$eventHeight = $event['Height']; + +if ( !isset( $rate ) ) + $_REQUEST['rate'] = reScale( RATE_BASE, $event['DefaultRate'], ZM_WEB_DEFAULT_RATE ); + +$eventPath = ZM_DIR_EVENTS.'/'.getEventPath( $event ); + +$videoFormats = array(); +$ffmpegFormats = preg_split( '/\s+/', ZM_FFMPEG_FORMATS ); +foreach ( $ffmpegFormats as $ffmpegFormat ) +{ + preg_match( '/^([^*]+)(\**)$/', $ffmpegFormat, $matches ); + $videoFormats[$matches[1]] = $matches[1]; + if ( $matches[2] == '*' ) + $defaultVideoFormat = $matches[1]; + elseif ( $matches[2] == '**' ) + $defaultPhoneFormat = $matches[1]; +} +if ( !isset($_REQUEST['videoFormat']) ) +{ + if ( isset($defaultPhoneFormat) ) + $_REQUEST['videoFormat'] = $defaultPhoneFormat; + elseif ( isset($defaultVideoFormat) ) + $_REQUEST['videoFormat'] = $defaultVideoFormat; + else + $videoFormat = $ffmpegFormats[0]; +} + +if ( !empty($_REQUEST['generate']) ) +{ + $videoFile = createVideo( $event, $_REQUEST['videoFormat'], $_REQUEST['rate'], $videoSize, !empty($_REQUEST['overwrite']) ); +} + +$videoFiles = array(); +if ( $dir = opendir( $eventPath ) ) +{ + while ( ($file = readdir( $dir )) !== false ) + { + $file = $eventPath.'/'.$file; + if ( is_file( $file ) ) + { + if ( preg_match( '/-S([\da-z]+)\.(?:'.join( '|', $videoFormats ).')$/', $file, $matches ) ) + { + if ( $matches[1] == $videoSize ) + { + $videoFiles[] = $file; + } + } + } + } + closedir( $dir ); +} + +if ( isset($_REQUEST['download']) ) +{ + header( "Content-type: ".getMimeType($videoFiles[$_REQUEST['download']])); + header( "Content-length: ".filesize($videoFiles[$_REQUEST['download']])); + header( "Content-disposition: attachment; filename=".preg_replace( "/^.*\//", "", $videoFiles[$_REQUEST['download']] )."; size=".filesize($videoFiles[$_REQUEST['download']]) ); + readfile( $videoFiles[$_REQUEST['download']] ); + exit; +} + +xhtmlHeaders( __FILE__, $SLANG['Video'].' - '.$event['Name'] ); +?> + +
+
+
+ + + + + + + + + + + + + + +
checked="checked"/>
+
+
+ +

+ +

+ + +

+ + + + + + + + + 0 ) + { + $index = 0; + foreach ( $videoFiles as $file ) + { + preg_match( '/^(.+)-((?:r[_\d]+)|(?:F[_\d]+))-((?:s[_\d]+)|(?:S[0-9a-z]+))\.([^.]+)$/', $file, $matches ); + if ( preg_match( '/^r(.+)$/', $matches[2], $temp_matches ) ) + { + $rate = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) ); + $rateText = isset($rates[$rate])?$rates[$rate]:($rate."x"); + } + elseif ( preg_match( '/^F(.+)$/', $matches[2], $temp_matches ) ) + { + $rateText = $temp_matches[1]."fps"; + } + if ( preg_match( '/^s(.+)$/', $matches[3], $temp_matches ) ) + { + $scale = (int)(100 * preg_replace( '/_/', '.', $temp_matches[1] ) ); + $scaleText = isset($scales[$scale])?$scales[$scale]:($scale."x"); + } + elseif ( preg_match( '/^S(.+)$/', $matches[3], $temp_matches ) ) + { + $scaleText = $temp_matches[1]; + } +?> + + + + + + + + +
 / 
+ +

+ +
+
+ + diff --git a/web/skins/mobile/views/watch.php b/web/skins/mobile/views/watch.php new file mode 100644 index 000000000..8d481e108 --- /dev/null +++ b/web/skins/mobile/views/watch.php @@ -0,0 +1,154 @@ + + +
+
+

 -  fps

+

+ + + +

+ +
+ +
+ +
+ + + +
+ +
+
+ + diff --git a/web/skins/xml/Makefile.am b/web/skins/xml/Makefile.am new file mode 100644 index 000000000..2c30d19a3 --- /dev/null +++ b/web/skins/xml/Makefile.am @@ -0,0 +1,10 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/xml + +SUBDIRS = \ + includes \ + views + +dist_web_DATA = \ + skin.php diff --git a/web/skins/xml/Makefile.in b/web/skins/xml/Makefile.in new file mode 100644 index 000000000..0c89d073f --- /dev/null +++ b/web/skins/xml/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/xml +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/xml +SUBDIRS = \ + includes \ + views + +dist_web_DATA = \ + skin.php + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/xml/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/xml/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dist_webDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/xml/includes/Makefile.am b/web/skins/xml/includes/Makefile.am new file mode 100644 index 000000000..c6128f8a2 --- /dev/null +++ b/web/skins/xml/includes/Makefile.am @@ -0,0 +1,8 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/skins/xml/includes + +dist_web_DATA = \ + init.php \ + config.php \ + functions.php diff --git a/web/skins/xml/includes/Makefile.in b/web/skins/xml/includes/Makefile.in new file mode 100644 index 000000000..37b45e7c8 --- /dev/null +++ b/web/skins/xml/includes/Makefile.in @@ -0,0 +1,455 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/xml/includes +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/skins/xml/includes +dist_web_DATA = \ + init.php \ + config.php \ + functions.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/xml/includes/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/xml/includes/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/xml/includes/config.php b/web/skins/xml/includes/config.php new file mode 100644 index 000000000..538938df2 --- /dev/null +++ b/web/skins/xml/includes/config.php @@ -0,0 +1,155 @@ + "100x", + "5000" => "50x", + "2500" => "25x", + "1000" => "10x", + "400" => "4x", + "200" => "2x", + "100" => $SLANG['Real'], + "50" => "1/2x", + "25" => "1/4x", +); + +$scales = array( + "400" => "4x", + "300" => "3x", + "200" => "2x", + "150" => "1.5x", + "100" => $SLANG['Actual'], + "75" => "3/4x", + "50" => "1/2x", + "33" => "1/3x", + "25" => "1/4x", +); + +$bwArray = array( + "high" => $SLANG['High'], + "medium" => $SLANG['Medium'], + "low" => $SLANG['Low'] +); + +/* Check if ZM_WEB_L_CAN_STREAM and ZM_WEB_L_STREAM_METHOD are defined */ +if (!defined("ZM_WEB_L_CAN_STREAM")) { + define ("ZM_WEB_L_CAN_STREAM", 1); + define ("ZM_WEB_M_CAN_STREAM", 1); + define ("ZM_WEB_H_CAN_STREAM", 1); +} +if (!defined("ZM_WEB_L_STREAM_METHOD")) { + define ("ZM_WEB_L_STREAM_METHOD", "jpeg"); + define ("ZM_WEB_M_STREAM_METHOD", "jpeg"); + define ("ZM_WEB_H_STREAM_METHOD", "jpeg"); +} + +switch ( $_COOKIE['zmBandwidth'] ) +{ + case "high" : + { + define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_H_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_H_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor + define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_H_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) + define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_H_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window + define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_H_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events + define( "ZM_WEB_CAN_STREAM", ZM_WEB_H_CAN_STREAM ); // Override the automatic detection of browser streaming capability + define( "ZM_WEB_STREAM_METHOD", ZM_WEB_H_STREAM_METHOD ); // Which method should be used to send video streams to your browser + define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_H_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%) + define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_H_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%) + define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_H_VIDEO_BITRATE ); // What the bitrate of any streamed video should be + define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_H_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be + define( "ZM_WEB_SCALE_THUMBS", ZM_WEB_H_SCALE_THUMBS ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling + define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_H_EVENTS_VIEW ); // What the default view of multiple events should be. + define( "ZM_WEB_SHOW_PROGRESS", ZM_WEB_H_SHOW_PROGRESS ); // Whether to show the progress of replay in event view. + define( "ZM_WEB_AJAX_TIMEOUT", ZM_WEB_H_AJAX_TIMEOUT ); // Timeout to use for Ajax requests, no timeout used if unset + break; + } + case "medium" : + { + define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_M_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_M_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor + define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_M_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) + define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_M_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window + define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_M_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events + define( "ZM_WEB_CAN_STREAM", ZM_WEB_M_CAN_STREAM ); // Override the automatic detection of browser streaming capability + define( "ZM_WEB_STREAM_METHOD", ZM_WEB_M_STREAM_METHOD ); // Which method should be used to send video streams to your browser + define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_M_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%) + define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_M_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%) + define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_M_VIDEO_BITRATE ); // What the bitrate of any streamed video should be + define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_M_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be + define( "ZM_WEB_SCALE_THUMBS", ZM_WEB_M_SCALE_THUMBS ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling + define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_M_EVENTS_VIEW ); // What the default view of multiple events should be. + define( "ZM_WEB_SHOW_PROGRESS", ZM_WEB_M_SHOW_PROGRESS ); // Whether to show the progress of replay in event view. + define( "ZM_WEB_AJAX_TIMEOUT", ZM_WEB_M_AJAX_TIMEOUT ); // Timeout to use for Ajax requests, no timeout used if unset + break; + } + case "low" : + { + define( "ZM_WEB_REFRESH_MAIN", ZM_WEB_L_REFRESH_MAIN ); // How often (in seconds) the main console window refreshes + define( "ZM_WEB_REFRESH_CYCLE", ZM_WEB_L_REFRESH_CYCLE ); // How often the cycle watch windows swaps to the next monitor + define( "ZM_WEB_REFRESH_IMAGE", ZM_WEB_L_REFRESH_IMAGE ); // How often the watched image is refreshed (if not streaming) + define( "ZM_WEB_REFRESH_STATUS", ZM_WEB_L_REFRESH_STATUS ); // How often the little status frame refreshes itself in the watch window + define( "ZM_WEB_REFRESH_EVENTS", ZM_WEB_L_REFRESH_EVENTS ); // How often the event listing is refreshed in the watch window, only for recent events + define( "ZM_WEB_CAN_STREAM", ZM_WEB_L_CAN_STREAM ); // Override the automatic detection of browser streaming capability + define( "ZM_WEB_STREAM_METHOD", ZM_WEB_L_STREAM_METHOD ); // Which method should be used to send video streams to your browser + define( "ZM_WEB_DEFAULT_SCALE", ZM_WEB_L_DEFAULT_SCALE ); // What the default scaling factor applied to 'live' or 'event' views is (%) + define( "ZM_WEB_DEFAULT_RATE", ZM_WEB_L_DEFAULT_RATE ); // What the default replay rate factor applied to 'event' views is (%) + define( "ZM_WEB_VIDEO_BITRATE", ZM_WEB_L_VIDEO_BITRATE ); // What the bitrate of any streamed video should be + define( "ZM_WEB_VIDEO_MAXFPS", ZM_WEB_L_VIDEO_MAXFPS ); // What the maximum frame rate of any streamed video should be + define( "ZM_WEB_SCALE_THUMBS", ZM_WEB_L_SCALE_THUMBS ); // Image scaling for thumbnails, bandwidth versus cpu in rescaling + define( "ZM_WEB_EVENTS_VIEW", ZM_WEB_L_EVENTS_VIEW ); // What the default view of multiple events should be. + define( "ZM_WEB_SHOW_PROGRESS", ZM_WEB_L_SHOW_PROGRESS ); // Whether to show the progress of replay in event view. + define( "ZM_WEB_AJAX_TIMEOUT", ZM_WEB_L_AJAX_TIMEOUT ); // Timeout to use for Ajax requests, no timeout used if unset + break; + } +} + +?> diff --git a/web/skins/xml/includes/functions.php b/web/skins/xml/includes/functions.php new file mode 100644 index 000000000..ef7b33a6c --- /dev/null +++ b/web/skins/xml/includes/functions.php @@ -0,0 +1,455 @@ + $maj) return 1; + if ((getClientVerMaj() == $maj) && (getClientVerMin() >= $min)) return 1; + return 0; +} +function logXmlErr($str) +{ + logXml($str, 1); +} +function logXml($str, $err = 0) +{ + if (!defined("ZM_EYEZM_DEBUG")) { + /* Check session variable */ + if (isset($_SESSION['xml_debug'])) define("ZM_EYEZM_DEBUG", $_SESSION['xml_debug']); + else define ("ZM_EYEZM_DEBUG", "0"); + } + if (!defined("ZM_EYEZM_LOG_TO_FILE")) { + /* Check session variable */ + if (isset($_SESSION['xml_log_to_file'])) define("ZM_EYEZM_LOG_TO_FILE", $_SESSION['xml_log_to_file']); + else define ("ZM_EYEZM_LOG_TO_FILE", "1"); + } + if (!defined("ZM_EYEZM_LOG_FILE")) { + /* Check session variable */ + if (isset($_SESSION['xml_log_file'])) define("ZM_EYEZM_LOG_FILE", $_SESSION['xml_log_file']); + else define ("ZM_EYEZM_LOG_FILE", "/tmp/zm_xml.log"); + } + /* Only log if debug is enabled */ + if (ZM_EYEZM_DEBUG == 0) return; + /* Logging is enabled, set log string */ + $logstr = "XML_LOG (".($err?"ERROR":"NOTICE")."): ".$str.(ZM_EYEZM_LOG_TO_FILE?"\n":""); + if (ZM_EYEZM_LOG_TO_FILE) { + error_log("[".date("r")."] ".$logstr, 3, ZM_EYEZM_LOG_FILE); + } else { + error_log($logstr); + } +} +/* Returns defval if varname is not set, otherwise return varname */ +function getset($varname, $defval) +{ + if (isset($_GET[$varname])) return $_GET[$varname]; + return $defval; +} +function xml_header() +{ + header ("content-type: text/xml"); + echo ""; +} +function xml_tag_val($tag, $val) +{ + echo "<".$tag.">".$val.""; +} +function xml_tag_sec($tag, $open) +{ + if ($open) $tok = "<"; + else $tok = ""; +} +function xhtmlHeaders( $file, $title ) +{ +?> + + + + + + + /dev/null")) > 0) { + /* More than one match */ + return TRUE; + } else { + /* Check -formats tag also if we fail -codecs */ + if (preg_match("/\b".$codec."\b/", shell_exec(getFfmpegPath()." -formats 2> /dev/null")) > 0) return TRUE; + return FALSE; + } +} +function exeExists($exepath) +{ + $path = trim($exepath); + return (file_exists($path) && is_readable($path) && ($path != "")); +} +/* Returns whether ffmpeg exists or not */ +function ffmpegExists() +{ + return exeExists(getFfmpegPath()); +} +/* Returns with PHP-GD exists */ +function gdExists() +{ + if (extension_loaded('gd') && function_exists('gd_info')) { + return TRUE; + } + return FALSE; +} + +function getFfmpeg264FoutParms($br, $fout) +{ + $ffparms = "-analyzeduration 0 -acodec copy"; + $ffparms .= " -vcodec libx264 -b ".$br; + $ffparms .= " -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8"; + $ffparms .= " -subq 5 -trellis 1 -refs 1 -coder 0 -me_range 16 -keyint_min 25"; + $ffparms .= " -sc_threshold 40 -i_qfactor 0.71 -bt 16k"; + $ffparms .= " -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6"; + $ffparms .= " -qmin 10 -qmax 51 -qdiff 4 -level 30"; + $ffparms .= " -g 30 -analyzeduration 0 -async 2 ".$fout." 2> /dev/null"; + return $ffparms; +} +/** Return FFMPEG parameters for H264 streaming */ +function getFfmpeg264Str($width, $height, $br, $fin, $fout) +{ + $ffparms = getFfmpeg264FoutParms($br, $fout); + $ffstr = getFfmpegPath()." -t ".ZM_EYEZM_H264_MAX_DURATION." -analyzeduration 0 -i "; + $ffstr .= $fin." -f mpegts ".$ffparms; + return $ffstr; +} +/** Returns true when monitor exists */ +function isMonitor($monitor) +{ + $query = "select Id from Monitors where Id = ".$monitor; + $res = dbFetchOne(escapeSql($query)); + if ($res) return TRUE; + logXml("Monitor ID ".$monitor." does not exist"); + return FALSE; +} +/** Returns the width and height of a monitor */ +function getMonitorDims($monitor) +{ + $query = "select Width,Height from Monitors where Id = ".$monitor; + $res = dbFetchOne(escapeSql($query)); + return $res; +} +/** Returns the temp directory for H264 encoding */ +function getTempDir() +{ + /* Assume that the directory structure is /skins/xml/views */ + return dirname(__FILE__)."/../../../temp"; +} +/** Returns the name of the m3u8 playlist based on monitor */ +function m3u8fname($monitor) { + return "stream_".$monitor.".m3u8"; +} + +/** Erases the M3u8 and TS file names for a given monitor */ +function eraseH264Files($monitor) { + /** NOTE: This command executes an 'rm' command, so $monitor parameter + * should be properly validated before executing */ + /* Remove wdir/.m3u8 and wdir/sample_*.ts */ + shell_exec("rm -f ".getTempDir()."/".m3u8fname($monitor)." ".getTempDir()."/sample_".$monitor."*.ts"); +} +function kill264proc($monitor) { + /** NOTE: This command executes an 'kill' command, so $monitor parameter + * should be properly validated before executing */ + $pid = trim(shell_exec("pgrep -f -x \"zmstreamer -m ".$monitor."\"")); + if ($pid == "") { + logXml("No PID found for ZMStreamer to kill"); + } else { + shell_exec("kill -9 ".$pid); + logXml("Killed process ".$pid." for Monitor ".$monitor); + } +} +/** Return the command-line shell function to setup H264 stream */ +function stream264fn ($mid, $width, $height, $br) { + $cdir = "./temp"; + $zmstrm = "zmstreamer -m ".$mid." 2> /dev/null"; + $ffstr = getFfmpeg264Str($width, $height, $br, "-", "-"); + $seg = "segmenter - ".ZM_EYEZM_SEG_DURATION." ".$cdir."/sample_".$mid." ".$cdir."/".m3u8fname($mid)." ../ 2> /dev/null"; + $url = $zmstrm . " | ".$ffstr." | " . $seg; + return "nohup ".$url." & echo $!"; +} + +/** Generate the web-page presented to the viewer when using H264 */ +function h264vidHtml($width, $height, $monitor, $br, $thumbsrc) { + function printTermLink() { + $str = "H264 Streaming Launching...
Tap to re-load if stream fails"; + $str2 = "document.getElementById(\"loaddiv\").innerHTML = \"".$str."\";"; + echo $str2; + + } + $ajaxUrl = "?view=actions&action=spawn264&&monitor=".$monitor."&br=".$br; + /* Call these two directly to bypass server blocking issues */ + $ajax2Url = "./skins/xml/views/actions.php?action=chk264&monitor=".$monitor; + $ajax2Url .= "&timeout=".ZM_EYEZM_H264_TIMEOUT; + $ajax3Url = "./skins/xml/views/actions.php?action=kill264&monitor=".$monitor; +?> + + + + + + + +
+
+Initializing H264 Stream ()...
+This may take a few seconds +
+
+ +
+ +
+ + + diff --git a/web/skins/xml/includes/init.php b/web/skins/xml/includes/init.php new file mode 100644 index 000000000..acb6c3546 --- /dev/null +++ b/web/skins/xml/includes/init.php @@ -0,0 +1,2 @@ + diff --git a/web/skins/xml/skin.php b/web/skins/xml/skin.php new file mode 100644 index 000000000..d797c7b08 --- /dev/null +++ b/web/skins/xml/skin.php @@ -0,0 +1,46 @@ + diff --git a/web/skins/xml/views/Makefile.am b/web/skins/xml/views/Makefile.am new file mode 100644 index 000000000..ab9147ae4 --- /dev/null +++ b/web/skins/xml/views/Makefile.am @@ -0,0 +1,11 @@ +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = + +webdir = @WEB_PREFIX@/skins/xml/views + +dist_web_DATA = \ + console.php \ + actions.php \ + none.php \ + notfound.png diff --git a/web/skins/xml/views/Makefile.in b/web/skins/xml/views/Makefile.in new file mode 100644 index 000000000..77440a95e --- /dev/null +++ b/web/skins/xml/views/Makefile.in @@ -0,0 +1,656 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/skins/xml/views +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = +webdir = @WEB_PREFIX@/skins/xml/views +dist_web_DATA = \ + console.php \ + actions.php \ + none.php \ + notfound.png + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/skins/xml/views/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/skins/xml/views/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile $(DATA) +installdirs: installdirs-recursive +installdirs-am: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dist_webDATA \ + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-pdf install-pdf-am install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/skins/xml/views/actions.php b/web/skins/xml/views/actions.php new file mode 100644 index 000000000..f6f62adca --- /dev/null +++ b/web/skins/xml/views/actions.php @@ -0,0 +1,393 @@ + */ + if (!canEdit('Events')) { + logXmlErr("User ".$user['Username']. " doesn't have edit Events perms"); + exit; + } + if (!isset($_REQUEST['eid'])) { + logXmlErr("EID not set for action delete-event"); + exit; + } + $eid = validInteger($_REQUEST['eid']); + $url = "./index.php?view=request&request=event&id=".$eid."&action=delete"; + header("Location: ".$url); + exit; + + } else if (!strcmp($action, "spawn264")) { + /* ACTION: Spawn 264 streaming process. + * Parms: [br|width|height] */ + if (!canView('Stream')) { + logXmlErr("User ".$user['Username']. " doesn't have view Stream perms"); + exit; + } + if (!isset($_GET['monitor'])) { + logXmlErr("Not all parameters specified for spawn264"); + exit; + } + $monitor = validInteger($_REQUEST['monitor']); + if (!isMonitor($monitor)) exit; + $dims = getMonitorDims($monitor); + $width = validInteger(getset('width', $dims['Width'])); + $height = validInteger(getset('height', $dims['Height'])); + $br = validString(getset('br', ZM_EYEZM_H264_DEFAULT_BR)); + /* Check that we can stream first */ + if (!canStream264()) { + /* canStream264 will print out error */ + exit; + } + $streamUrl = stream264fn($monitor, $width, $height, $br); + logXml("Using H264 Pipe Function: ".$streamUrl); + $pid = shell_exec($streamUrl); + logXml("Streaming Process for monitor ".$monitor." ended, cleaning up files"); + eraseH264Files($monitor); + exit; + + } else if (!strcmp($action, "kill264")) { + /* ACTION: Kill existing H264 stream process and cleanup files. + * Parms: . + * NOTE: This will be called directly by path, so include files + * may not be available */ + session_start(); + require_once(dirname(__FILE__)."/../includes/functions.php"); + if (!isset($_GET['monitor'])) { + logXmlErr("Not all parameters specified for kill264"); + exit; + } + $monitor = validInteger($_GET['monitor']); + kill264proc($monitor); + logXml("Killed Segmenter process for monitor ".$monitor); + exit; + + } else if (!strcmp($action, "chk264")) { + /* ACTION: Simply stalls while checking for 264 file. + * Parms: + * NOTE: This will be called directly by path, so include files + * may not be available */ + session_start(); + require_once(dirname(__FILE__)."/../includes/functions.php"); + if (!isset($_GET['monitor']) || !isset($_GET['timeout'])) { + logXmlErr("Monitor not specified for chk264"); + exit; + } + $monitor = validInteger($_GET['monitor']); + $path = getTempDir()."/".m3u8fname($monitor); + /* Wait for the second sample to become available */ + $tsfile = getTempDir()."/sample_".$monitor."-2.ts"; + /* Setup timeout */ + $startTime = time(); + $timeout = validInteger($_GET['timeout']); + while (!file_exists($path) || !file_exists($tsfile)) { + if (time() > $startTime + $timeout) { + logXmlErr("Timed out waiting for stream to start, exiting..."); + kill264proc($monitor); + exit; + } + usleep(10000); + } + logXml("File exists, stream created after ".(time()-$startTime)." sec"); + exit; + + } else if (!strcmp($action, "feed")) { + /* ACTION: View a feed. Parms: [height|width|fps|scale|vcodec|br] */ + if (!canView('Stream')) { + logXmlErr("User ".$user['Username']. " doesn't have view Stream perms"); + exit; + } + /* Check that required variables are set */ + if (!isset($_REQUEST['monitor'])) { + logXmlErr("Not all parameters set for action view-feed"); + exit; + } + $monitor = validInteger($_REQUEST['monitor']); + if (!isMonitor($monitor)) exit; + $dims = getMonitorDims($monitor); + $width = validInteger(getset('width', $dims['Width'])); + $height = validInteger(getset('height', $dims['Height'])); + $fps = validInteger(getset('fps', ZM_WEB_VIDEO_MAXFPS)); + $scale = validInteger(getset('scale', 100)); + $vcodec = validString(getset('vcodec', ZM_EYEZM_FEED_VCODEC)); + /* Select which codec we want */ + if (!strcmp($vcodec, "h264")) { + /* Validate that we can in fact stream H264 */ + if (!canStream264()) { + /* canStream264 will print out error if + * there is one */ + echo "Server cannot stream H264. Check eyeZm log for details"; + exit; + } + if (!requireVer("1", "2")) { + echo "H264 Streaming requires eyeZm v1.2 or above"; + logXmlErr("H264 Streaming requires eyeZm v1.2 or above"); + exit; + } + $br = validString(getset('br', ZM_EYEZM_H264_DEFAULT_BR)); + /* H264 processing */ + noCacheHeaders(); + /* Kill any existing processes and files */ + kill264proc($monitor); + eraseH264Files($monitor); + logXml("Streaming H264 on Monitor ".$monitor.", ".$width."x".$height." @".$br); + /* Get thumbnail source */ + $thumbsrc = + getStreamSrc( array( + "mode=single", + "monitor=".$monitor, + "scale=".$scale, + "maxfps=".$fps, + "buffer=1000" + ) ); + logXml("Using thumbnail image from ".$thumbsrc); + /* Generate H264 Web-page */ + echo "\n"; + h264vidHtml($width, $height, $monitor, $br, $thumbsrc); + } else if (!strcmp($vcodec, "mjpeg")) { + /* MJPEG streaming */ + /* If $fps=0, get a single-shot */ + if (!$fps) { + /* single-shot */ + $streamSrc = + getStreamSrc( array( + "mode=single", + "monitor=".$monitor, + "scale=".$scale, + "maxfps=0", + "buffer=1000" + ) ); + } else { + $streamSrc = + getStreamSrc( array( + "mode=jpeg", + "monitor=".$monitor, + "scale=".$scale, + "maxfps=".$fps, + "buffer=1000" + ) ); + } + noCacheHeaders(); + xhtmlHeaders( __FILE__, "Stream" ); + logXml("Streaming MJPEG on Monitor ".$monitor.", ".$width."x".$height." @".$fps."fps"); + echo "\n"; + echo "\n"; + echo "
\n"; + logXml("Using stream source: ".$streamSrc); + outputImageStream("liveStream", $streamSrc, $width, $height, "stream"); + echo "
"; + } else { + logXmlErr("Unsupported codec ".$vcodec." selected for streaming"); + echo("Unsupported codec ".$vcodec." selected for streaming"); + } + exit; + + } else if (!strcmp($action, "vevent")) { + /* ACTION: View an event. Parms: [fps|vcodec|br] */ + if (!canView('Events')) { + logXmlErr("User ".$user['Username']. " doesn't have view Events perms"); + exit; + } + if (!isset($_GET['eid'])) { + logXmlErr("Not all parameters set for Action View-event"); + exit; + } + /* Grab event from the database */ + $eid = validInteger($_GET['eid']); + $eventsSql = "select E.Id, E.MonitorId, E.Name, E.StartTime, E.Length, E.Frames from Events as E where (E.Id = ".$eid.")"; + $event = dbFetchOne(escapeSql($eventsSql)); + /* Check if exists */ + if (!$event) { + logxmlErr("Requested event ID ".$eid." does not exist"); + exit; + } + /* Calculate FPS */ + $fps = validInteger(getset('fps',ceil($event['Frames'] / $event['Length']))); + $vcodec = validString(getset('vcodec', ZM_EYEZM_EVENT_VCODEC)); + $baseURL = ZM_PATH_WEB."/".getEventPathSafe($event); + /* Here we validate the codec. + * Check that FFMPEG exists and supports codecs */ + if (!strcmp($vcodec, "mpeg4")) { + if (!ffmpegSupportsCodec("mpeg4")) { + logXmlErr("FFMPEG not installed, accessible in path/ZM_PATH_FFMPEG, or doesn't support mpeg4"); + exit; + } + /* Can generate, we are good to go */ + $fname = "capture.mov"; + $ffparms = "-vcodec mpeg4 -r ".ZM_EYEZM_EVENT_FPS." ".$baseURL."/".$fname." 2> /dev/null"; + + } else if (!strcmp($vcodec, "h264")) { + if (!ffmpegSupportsCodec("libx264")) { + logXmlErr("FFMPEG not installed, accessible in path/ZM_PATH_FFMPEG, or doesn't support H264"); + exit; + } + if (!requireVer("1","2")) { + logXmlErr("H264 Event viewing requires eyeZm v1.2 or greater"); + exit; + } + /* Good to go */ + $fname = "capture.mp4"; + $ffparms = getFfmpeg264FoutParms( + validString(getset('br',ZM_EYEZM_H264_DEFAULT_EVBR)), + $baseURL."/".$fname); + + } else { + logXmlErr("Unknown codec ".$vcodec." selected for event viewing"); + exit; + } + logXml("Selected ".$vcodec." for viewing event ".$event['Id']); + $fnameOut = $baseURL."/".$fname; + $shellCmd = getFfmpegPath()." -y -r ".$fps." -i ".$baseURL."/%0".ZM_EVENT_IMAGE_DIGITS."d-capture.jpg"; + $shellCmd .= " ".$ffparms; + logXml("Encoding event with command: ".$shellCmd); + $shellOutput = shell_exec($shellCmd); + /* Check that file exists */ + if (!file_exists(trim($fnameOut))) { + logXmlErr("Generate Event ".$event['Id']." file ".$fnameOut." does not exist"); + exit; + } + $url = "./".getEventPathSafe($event)."/".$fname; + logXml("Loading Event URL ".$url); + header("Location: ".$url); + exit; + + } else if (!strcmp($action, "vframe")) { + /* ACTION: View a frame given by an event and frame-id. Parms: [alarm | analyze | qty | scale] + * If 'alarm' is set, the returned frame will be the -th alarm frame. If 'analyze' is set, + * the returned frame will be the %03d-analyse frame instead of %03d-capture, if ZM_CREATE_ANALYSIS_IMAGES + * is set. Otherwise it just returns the captured frame. + * If qty is set, it will apply a quality factor from 0-100, and if width is set, it will scale the jpeg accordingly + */ + if (!isset($_GET['eid']) || !isset($_GET['frame'])) { + logXmlErr("Not all parameters set for action view-frame"); + exit; + } + $eid = validInteger($_GET['eid']); + $frame = validInteger($_GET['frame']); + $eventsSql = "select E.Id, E.MonitorId, E.Name, E.StartTime, E.Length, E.Frames from Events as E where (E.Id = ".$eid.")"; + $event = dbFetchOne(escapeSql($eventsSql)); + $qty = validInteger(getset('qty', 100)); + if ($qty > 100) $qty = 100; + $scale = validInteger(getset('scale', 100)); + if (!$event) { + logxmlErr("Requested event ID ".$eid." does not exist"); + exit; + } + /* Figure out the frame number. If 'alarm' is not set, this is just equal to the parameter. + * If 'alarm' is set, need to query DB and grab the -th item */ + if (isset($_GET['alarm'])) { + $frameSql = escapeSql("select * from Frames as F where (F.EventId = ".$eid.") "); + $frameSql .= " and (F.Type = 'Alarm') order by F.FrameId"; + $i=0; + foreach (dbFetchAll($frameSql) as $dbframe) { + if ($i == $frame) { + $frame = $dbframe['FrameId']; + break; + } + $i++; + } + } + if (isset($_GET['analyze']) && ZM_CREATE_ANALYSIS_IMAGES) { + $suffix = "analyse"; + } else { + $suffix = "capture"; + } + /* A frame index of 0 is invalid, so if we see this, just use frame 1 */ + if (!$frame) $frame = 1; + /* Suffix based on 'analyze' */ + $fname = sprintf("%0".ZM_EVENT_IMAGE_DIGITS."d-%s.jpg", $frame, $suffix); + $url = "./".getEventPathSafe($event)."/".$fname; + if (!file_exists($url)) { + logXmlErr("Invalid frame image requested: ".$url); + $url = "./skins/xml/views/notfound.png"; + } + /* Check if the image needs any processing - check for GD if requested */ + if (($scale != 100) || ($qty < 100)) { + if (!gdExists()) { + logXmlErr("Lib GD is not loaded, but required for image scaling functions"); + $url = "./skins/xml/views/notfound.png"; + } else if (!$img = imagecreatefromjpeg($url)) { + logXmlErr("Could not load JPEG from ".$url); + $url = "./skins/xml/views/notfound.png"; + } else { + /* GD exists and we read the file ok */ + header('Content-type: image/jpeg'); + /* Check if resizing is needed */ + if ($scale != 100) { + list($width_orig, $height_orig) = getimagesize($url); + $width_new = $width_orig * ($scale/100); + $height_new = $height_orig * ($scale/100); + $img_new = imagecreatetruecolor($width_new, $height_new); + imagecopyresampled($img_new, $img, 0, 0, 0, 0, $width_new, $height_new, $width_orig, $height_orig); + imagejpeg($img_new, NULL, $qty); + } else { + imagejpeg($img, NULL, $qty); + } + exit; + } + } + header("Location: ".$url); + exit; + + } else if (!strcmp($action, "state")) { + /* ACTION: Change the state of the system. Parms: */ + if (!canEdit('System')) { + logXmlErr("User ".$user['Username']. " doesn't have edit System perms"); + exit; + } + if (!isset($_GET['state'])) { + logXmlErr("Server state not specified for action"); + exit; + } + $url = "./index.php?view=none&action=state&runState=".validString($_GET['state']); + header("Location: ".$url); + exit; + + } else if (!strcmp($action, "func")) { + /* ACTION: Change state of the monitor. Parms: */ + if (!canEdit('Monitors')) { + logXmlErr("User ".$user['Username']. " doesn't have monitors Edit perms"); + exit; + } + if (!isset($_GET['mid']) || !isset($_GET['func']) || !isset($_GET['en'])) { + logXmlErr("Not all parameters specified for action Monitor state"); + exit; + } + $mid = validInteger($_GET['mid']); + if (!isMonitor($mid)) exit; + $url = "./index.php?view=none&action=function&mid=".$mid."&newFunction=".validString($_GET['func'])."&newEnabled=".validString($_GET['en']); + header("Location: ".$url); + exit; + + } else if (!strcmp($action, "vlog")) { + /* ACTION: View log file. Must have debug and log to file enabled, and sufficient perms + * Parms: [lines] */ + if (!canEdit('System')) { + logXmlErr("Insufficient permissions to view log file"); + echo "Insufficient permissions to view log file"; + exit; + } + if (!ZM_EYEZM_DEBUG || !ZM_EYEZM_LOG_TO_FILE) { + echo "eyeZm Debug (EYEZM_DEBUG) or log-to-file (EYEZM_LOG_TO_FILE) not enabled. Please enable first"; + exit; + } + if (!file_exists(ZM_EYEZM_LOG_FILE)) { + echo "Log file ".ZM_EYEZM_LOG_FILE." doesn't exist"; + exit; + } + $lines = validInteger(getset('lines',ZM_EYEZM_LOG_LINES)); + logXml("Returning last ".$lines." lines of eyeZm Log from ".ZM_EYEZM_LOG_FILE); + echo shell_exec("tail -n ".$lines." ".ZM_EYEZM_LOG_FILE); + echo "\n\n--- Showing last ".$lines." lines ---\n"; + echo "--- End of Log ---\n\n"; + } +} +?> diff --git a/web/skins/xml/views/console.php b/web/skins/xml/views/console.php new file mode 100644 index 000000000..d2668fc8a --- /dev/null +++ b/web/skins/xml/views/console.php @@ -0,0 +1,259 @@ + $SLANG['Events'], + "filter" => array( + "terms" => array( + ) + ), + ), + array( + "title" => $SLANG['Hour'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "-1 hour" ), + ) + ), + ), + array( + "title" => $SLANG['Day'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "-1 day" ), + ) + ), + ), + array( + "title" => $SLANG['Week'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "-7 day" ), + ) + ), + ), + array( + "title" => $SLANG['Month'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "0" ), + array( "cnj" => "and", "attr" => "DateTime", "op" => ">=", "val" => "-1 month" ), + ) + ), + ), + array( + "title" => $SLANG['Archived'], + "filter" => array( + "terms" => array( + array( "attr" => "Archived", "op" => "=", "val" => "1" ), + ) + ), + ), +); + +$running = daemonCheck(); +$status = $running?$SLANG['Running']:$SLANG['Stopped']; + +if ( $group = dbFetchOne( "select * from Groups where Id = '".(empty($_COOKIE['zmGroup'])?0:dbEscape($_COOKIE['zmGroup']))."'" ) ) + $groupIds = array_flip(split( ',', $group['MonitorIds'] )); + +$maxWidth = 0; +$maxHeight = 0; +$cycleCount = 0; +$minSequence = 0; +$maxSequence = 1; +$seqIdList = array(); +$monitors = dbFetchAll( "select * from Monitors order by Sequence asc" ); +$displayMonitors = array(); +for ( $i = 0; $i < count($monitors); $i++ ) +{ + if ( !visibleMonitor( $monitors[$i]['Id'] ) ) + { + continue; + } + if ( $group && !empty($groupIds) && !array_key_exists( $monitors[$i]['Id'], $groupIds ) ) + { + continue; + } + $monitors[$i]['Show'] = true; + if ( empty($minSequence) || ($monitors[$i]['Sequence'] < $minSequence) ) + { + $minSequence = $monitors[$i]['Sequence']; + } + if ( $monitors[$i]['Sequence'] > $maxSequence ) + { + $maxSequence = $monitors[$i]['Sequence']; + } + if (isset($_GET['nostatus'])) { + $monitors[$i]['zmc'] = 1; + $monitors[$i]['zma'] = 1; + } else { + $monitors[$i]['zmc'] = zmcStatus( $monitors[$i] ); + $monitors[$i]['zma'] = zmaStatus( $monitors[$i] ); + } + $monitors[$i]['ZoneCount'] = dbFetchOne( "select count(Id) as ZoneCount from Zones where MonitorId = '".$monitors[$i]['Id']."'", "ZoneCount" ); + $counts = array(); + for ( $j = 0; $j < count($eventCounts); $j++ ) + { + $filter = addFilterTerm( $eventCounts[$j]['filter'], count($eventCounts[$j]['filter']['terms']), array( "cnj" => "and", "attr" => "MonitorId", "op" => "=", "val" => $monitors[$i]['Id'] ) ); + parseFilter( $filter ); + $counts[] = "count(if(1".$filter['sql'].",1,NULL)) as EventCount$j"; + $monitors[$i]['eventCounts'][$j]['filter'] = $filter; + } + $sql = "select ".join($counts,", ")." from Events as E where MonitorId = '".$monitors[$i]['Id']."'"; + $counts = dbFetchOne( $sql ); + if ( $monitors[$i]['Function'] != 'None' ) + { + $cycleCount++; + $scaleWidth = reScale( $monitors[$i]['Width'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); + $scaleHeight = reScale( $monitors[$i]['Height'], $monitors[$i]['DefaultScale'], ZM_WEB_DEFAULT_SCALE ); + if ( $maxWidth < $scaleWidth ) $maxWidth = $scaleWidth; + if ( $maxHeight < $scaleHeight ) $maxHeight = $scaleHeight; + } + $monitors[$i] = array_merge( $monitors[$i], $counts ); + $seqIdList[] = $monitors[$i]['Id']; + $displayMonitors[] = $monitors[$i]; +} +$states = dbFetchAll("select * from States"); +/* XML Dump Starts here */ +xml_header(); +/* Print out the general section */ +xml_tag_sec("ZM_XML", 1); +xml_tag_sec("GENERAL", 1); +xml_tag_val("RUNNING", $running); +xml_tag_val("PROTOVER", ZM_EYEZM_PROTOCOL_VERSION); +xml_tag_val("FEATURESET", ZM_EYEZM_FEATURE_SET); +xml_tag_val("VERSION", ZM_VERSION); +xml_tag_val("CANSTR264", canStream264(1)); +xml_tag_val("GD", gdExists()); +xml_tag_val("FVCODEC", ZM_EYEZM_FEED_VCODEC); +xml_tag_val("FVTMT", ZM_EYEZM_H264_TIMEOUT); +xml_tag_val("USER", $user['Username']); +xml_tag_val("UID", $user['Id']); +/* Permissions block */ +xml_tag_sec("PERMS", 1); +xml_tag_val("STREAM", $user['Stream']); +xml_tag_val("EVENTS", $user['Events']); +xml_tag_val("CONTROL", $user['Control']); +xml_tag_val("MONITORS", $user['Monitors']); +xml_tag_val("DEVICES", $user['Devices']); +xml_tag_val("SYSTEM", $user['System']); +xml_tag_sec("PERMS", 0); +/* End permissions block */ +if (canEdit('System')) { + if ($running) { + xml_tag_val("STATE", "stop"); + xml_tag_val("STATE", "restart"); + } else { + xml_tag_val("STATE", "start"); + } + foreach ($states as $state) { + xml_tag_val("STATE", $state['Name']); + } +} +/* End general section */ +xml_tag_sec("GENERAL", 0); +/* Print out the monitors section */ +xml_tag_sec("MONITOR_LIST", 1); +foreach( $displayMonitors as $monitor ) +{ + if (!canView('Monitors')) continue; + xml_tag_sec("MONITOR", 1); + xml_tag_val("ID", $monitor['Id']); + xml_tag_val("NAME", $monitor['Name']); + xml_tag_val("FUNCTION", $monitor['Function']); + xml_tag_val("NUMEVENTS", $monitor['EventCount0']); + xml_tag_val("ENABLED", $monitor['Enabled']); + xml_tag_val("ZMC", $monitor['zmc']); + xml_tag_val("ZMA", $monitor['zma']); + xml_tag_val("STATE", ($monitor['zmc']!=1)?"ERROR":( + ($monitor['zma']==1)?"OK":"WARN")); + xml_tag_val("WIDTH", $monitor['Width']); + xml_tag_val("HEIGHT", $monitor['Height']); + + /* Form the data-base query for this monitor */ + $pageOffset = 0; + $offset = 0; + if (isset($_GET['numEvents'])) { + $numEvents = validInteger($_GET['numEvents']); + $eventsSql = "select E.Id,E.MonitorId,M.Name As MonitorName,E.Cause,E.Name,E.StartTime,E.Length,E.Frames,E.AlarmFrames,E.TotScore,E.AvgScore,E.MaxScore,E.Archived from Monitors as M inner join Events as E on (M.Id = E.MonitorId) and ( E.MonitorId = ".$monitor['Id']." ) order by E.StartTime desc"; + $eventsSql .= " limit ".$numEvents; + /* If there is an pageOff tag for this monitor, then retrieve the offset. Otherwise, don't specify offset */ + if (isset($_GET['pageOff'.$monitor['Id']])) { + /* If pageOffset is greater than we actually have, + * we need to adjust it */ + $pageOffset = validInteger($_GET['pageOff'.$monitor['Id']]); + if ($pageOffset >= ceil($monitor['EventCount0']/$numEvents)) { + $pageOffset = 0; + } + $offset = $pageOffset * $numEvents; + } + $eventsSql .= " offset ".$offset; + } else { + unset($eventsSql); + } + xml_tag_val("PAGEOFF", $pageOffset); + xml_tag_sec("EVENTS",1); + if (canView('Events') && isset($eventsSql)) { + foreach ( dbFetchAll( escapeSql($eventsSql) ) as $event ) + { + xml_tag_sec("EVENT",1); + xml_tag_val("ID",$event['Id']); + xml_tag_val("NAME",$event['Name']); + xml_tag_val("TIME", strftime( STRF_FMT_DATETIME_SHORTER, strtotime($event['StartTime']))); + xml_tag_val("DURATION", $event['Length']); + xml_tag_val("FRAMES", $event['Frames']); + xml_tag_val("FPS", ($event['Length'] > 0)?ceil($event['Frames']/$event['Length']):0); + xml_tag_val("TOTSCORE", $event['TotScore']); + xml_tag_val("AVGSCORE", $event['AvgScore']); + xml_tag_val("MAXSCORE", $event['MaxScore']); + /* Grab the max frame-id from Frames table. If AlarmFrames = 0, don't try + * to grab any frames, and just signal the max frame index as index 0 */ + $fridx = 1; + $alarmFrames = 1; + if ($event['AlarmFrames']) { + $framesSql = "select FrameId from Frames where (Type = 'Alarm') and (EventId = ".$event['Id'].") order by Score desc limit 1"; + $fr = dbFetchOne($framesSql); + $fridx = $fr['FrameId']; + $alarmFrames = $event['AlarmFrames']; + } + xml_tag_val("ALARMFRAMES", $alarmFrames); + xml_tag_val("MAXFRAMEID", $fridx); + xml_tag_sec("EVENT",0); + } + } + xml_tag_sec("EVENTS",0); + xml_tag_sec("MONITOR", 0); +} +xml_tag_sec("MONITOR_LIST", 0); +xml_tag_sec("ZM_XML", 0); +?> diff --git a/web/skins/xml/views/none.php b/web/skins/xml/views/none.php new file mode 100644 index 000000000..e69de29bb diff --git a/web/skins/xml/views/notfound.png b/web/skins/xml/views/notfound.png new file mode 100644 index 0000000000000000000000000000000000000000..219706897647c72375b90298de2d8a6622b7093d GIT binary patch literal 7332 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 R>Js3hJyX?HsZ+9j^?#`>R7U^+ literal 0 HcmV?d00001 diff --git a/web/tools/Makefile.am b/web/tools/Makefile.am new file mode 100644 index 000000000..29c91bc02 --- /dev/null +++ b/web/tools/Makefile.am @@ -0,0 +1,4 @@ +AUTOMAKE_OPTIONS = gnu + +SUBDIRS = \ + mootools diff --git a/web/tools/Makefile.in b/web/tools/Makefile.in new file mode 100644 index 000000000..b07349f77 --- /dev/null +++ b/web/tools/Makefile.in @@ -0,0 +1,595 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/tools +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-dvi-recursive install-exec-recursive \ + install-html-recursive install-info-recursive \ + install-pdf-recursive install-ps-recursive install-recursive \ + installcheck-recursive installdirs-recursive pdf-recursive \ + ps-recursive uninstall-recursive +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ + $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \ + distdir +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +am__relativize = \ + dir0=`pwd`; \ + sed_first='s,^\([^/]*\)/.*$$,\1,'; \ + sed_rest='s,^[^/]*/*,,'; \ + sed_last='s,^.*/\([^/]*\)$$,\1,'; \ + sed_butlast='s,/*[^/]*$$,,'; \ + while test -n "$$dir1"; do \ + first=`echo "$$dir1" | sed -e "$$sed_first"`; \ + if test "$$first" != "."; then \ + if test "$$first" = ".."; then \ + dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ + dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ + else \ + first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ + if test "$$first2" = "$$first"; then \ + dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ + else \ + dir2="../$$dir2"; \ + fi; \ + dir0="$$dir0"/"$$first"; \ + fi; \ + fi; \ + dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ + done; \ + reldir="$$dir2" +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +SUBDIRS = \ + mootools + +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/tools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/tools/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +$(RECURSIVE_CLEAN_TARGETS): + @fail= failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +html-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-dvi: install-dvi-recursive + +install-dvi-am: + +install-exec-am: + +install-html: install-html-recursive + +install-html-am: + +install-info: install-info-recursive + +install-info-am: + +install-man: + +install-pdf: install-pdf-recursive + +install-pdf-am: + +install-ps: install-ps-recursive + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: + +.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \ + install-am install-strip tags-recursive + +.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \ + all all-am check check-am clean clean-generic ctags \ + ctags-recursive distclean distclean-generic distclean-tags \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/tools/mootools/Makefile.am b/web/tools/mootools/Makefile.am new file mode 100644 index 000000000..958647796 --- /dev/null +++ b/web/tools/mootools/Makefile.am @@ -0,0 +1,18 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/tools/mootools + +dist_web_DATA = \ + mootools-core-1.3.2-nc.js \ + mootools-core-1.3.2-yc.js \ + mootools-more-1.3.2.1-nc.js \ + mootools-more-1.3.2.1-yc.js + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(webdir); rm -f mootools-core.js mootools-more.js ) + ( cd $(DESTDIR)$(webdir); ln -s mootools-core-1.3.2-yc.js mootools-core.js ) + ( cd $(DESTDIR)$(webdir); ln -s mootools-more-1.3.2.1-yc.js mootools-more.js ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -f mootools-* ) diff --git a/web/tools/mootools/Makefile.in b/web/tools/mootools/Makefile.in new file mode 100644 index 000000000..c44380251 --- /dev/null +++ b/web/tools/mootools/Makefile.in @@ -0,0 +1,468 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/tools/mootools +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/tools/mootools +dist_web_DATA = \ + mootools-core-1.3.2-nc.js \ + mootools-core-1.3.2-yc.js \ + mootools-more-1.3.2.1-nc.js \ + mootools-more-1.3.2.1-yc.js + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/tools/mootools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/tools/mootools/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-data-hook +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: install-am install-data-am install-strip uninstall-am + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-data-hook install-dist_webDATA install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-dist_webDATA uninstall-hook + + +# Yes, you are correct. This is a HACK! +install-data-hook: + ( cd $(DESTDIR)$(webdir); rm -f mootools-core.js mootools-more.js ) + ( cd $(DESTDIR)$(webdir); ln -s mootools-core-1.3.2-yc.js mootools-core.js ) + ( cd $(DESTDIR)$(webdir); ln -s mootools-more-1.3.2.1-yc.js mootools-more.js ) + +uninstall-hook: + @-( cd $(DESTDIR)$(webdir); rm -f mootools-* ) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/tools/mootools/mootools-core-1.3.2-nc.js b/web/tools/mootools/mootools-core-1.3.2-nc.js new file mode 100644 index 000000000..cba97ef7f --- /dev/null +++ b/web/tools/mootools/mootools-core-1.3.2-nc.js @@ -0,0 +1,5515 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff + +/* +--- + +name: Core + +description: The heart of MooTools. + +license: MIT-style license. + +copyright: Copyright (c) 2006-2010 [Valerio Proietti](http://mad4milk.net/). + +authors: The MooTools production team (http://mootools.net/developers/) + +inspiration: + - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php) + - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php) + +provides: [Core, MooTools, Type, typeOf, instanceOf, Native] + +... +*/ + +(function(){ + +this.MooTools = { + version: '1.3.2', + build: 'c9f1ff10e9e7facb65e9481049ed1b450959d587' +}; + +// typeOf, instanceOf + +var typeOf = this.typeOf = function(item){ + if (item == null) return 'null'; + if (item.$family) return item.$family(); + + if (item.nodeName){ + if (item.nodeType == 1) return 'element'; + if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace'; + } else if (typeof item.length == 'number'){ + if (item.callee) return 'arguments'; + if ('item' in item) return 'collection'; + } + + return typeof item; +}; + +var instanceOf = this.instanceOf = function(item, object){ + if (item == null) return false; + var constructor = item.$constructor || item.constructor; + while (constructor){ + if (constructor === object) return true; + constructor = constructor.parent; + } + return item instanceof object; +}; + +// Function overloading + +var Function = this.Function; + +var enumerables = true; +for (var i in {toString: 1}) enumerables = null; +if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; + +Function.prototype.overloadSetter = function(usePlural){ + var self = this; + return function(a, b){ + if (a == null) return this; + if (usePlural || typeof a != 'string'){ + for (var k in a) self.call(this, k, a[k]); + if (enumerables) for (var i = enumerables.length; i--;){ + k = enumerables[i]; + if (a.hasOwnProperty(k)) self.call(this, k, a[k]); + } + } else { + self.call(this, a, b); + } + return this; + }; +}; + +Function.prototype.overloadGetter = function(usePlural){ + var self = this; + return function(a){ + var args, result; + if (usePlural || typeof a != 'string') args = a; + else if (arguments.length > 1) args = arguments; + if (args){ + result = {}; + for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]); + } else { + result = self.call(this, a); + } + return result; + }; +}; + +Function.prototype.extend = function(key, value){ + this[key] = value; +}.overloadSetter(); + +Function.prototype.implement = function(key, value){ + this.prototype[key] = value; +}.overloadSetter(); + +// From + +var slice = Array.prototype.slice; + +Function.from = function(item){ + return (typeOf(item) == 'function') ? item : function(){ + return item; + }; +}; + +Array.from = function(item){ + if (item == null) return []; + return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item]; +}; + +Number.from = function(item){ + var number = parseFloat(item); + return isFinite(number) ? number : null; +}; + +String.from = function(item){ + return item + ''; +}; + +// hide, protect + +Function.implement({ + + hide: function(){ + this.$hidden = true; + return this; + }, + + protect: function(){ + this.$protected = true; + return this; + } + +}); + +// Type + +var Type = this.Type = function(name, object){ + if (name){ + var lower = name.toLowerCase(); + var typeCheck = function(item){ + return (typeOf(item) == lower); + }; + + Type['is' + name] = typeCheck; + if (object != null){ + object.prototype.$family = (function(){ + return lower; + }).hide(); + + } + } + + if (object == null) return null; + + object.extend(this); + object.$constructor = Type; + object.prototype.$constructor = object; + + return object; +}; + +var toString = Object.prototype.toString; + +Type.isEnumerable = function(item){ + return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' ); +}; + +var hooks = {}; + +var hooksOf = function(object){ + var type = typeOf(object.prototype); + return hooks[type] || (hooks[type] = []); +}; + +var implement = function(name, method){ + if (method && method.$hidden) return; + + var hooks = hooksOf(this); + + for (var i = 0; i < hooks.length; i++){ + var hook = hooks[i]; + if (typeOf(hook) == 'type') implement.call(hook, name, method); + else hook.call(this, name, method); + } + + var previous = this.prototype[name]; + if (previous == null || !previous.$protected) this.prototype[name] = method; + + if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){ + return method.apply(item, slice.call(arguments, 1)); + }); +}; + +var extend = function(name, method){ + if (method && method.$hidden) return; + var previous = this[name]; + if (previous == null || !previous.$protected) this[name] = method; +}; + +Type.implement({ + + implement: implement.overloadSetter(), + + extend: extend.overloadSetter(), + + alias: function(name, existing){ + implement.call(this, name, this.prototype[existing]); + }.overloadSetter(), + + mirror: function(hook){ + hooksOf(this).push(hook); + return this; + } + +}); + +new Type('Type', Type); + +// Default Types + +var force = function(name, object, methods){ + var isType = (object != Object), + prototype = object.prototype; + + if (isType) object = new Type(name, object); + + for (var i = 0, l = methods.length; i < l; i++){ + var key = methods[i], + generic = object[key], + proto = prototype[key]; + + if (generic) generic.protect(); + + if (isType && proto){ + delete prototype[key]; + prototype[key] = proto.protect(); + } + } + + if (isType) object.implement(prototype); + + return force; +}; + +force('String', String, [ + 'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search', + 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase' +])('Array', Array, [ + 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', + 'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight' +])('Number', Number, [ + 'toExponential', 'toFixed', 'toLocaleString', 'toPrecision' +])('Function', Function, [ + 'apply', 'call', 'bind' +])('RegExp', RegExp, [ + 'exec', 'test' +])('Object', Object, [ + 'create', 'defineProperty', 'defineProperties', 'keys', + 'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames', + 'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen' +])('Date', Date, ['now']); + +Object.extend = extend.overloadSetter(); + +Date.extend('now', function(){ + return +(new Date); +}); + +new Type('Boolean', Boolean); + +// fixes NaN returning as Number + +Number.prototype.$family = function(){ + return isFinite(this) ? 'number' : 'null'; +}.hide(); + +// Number.random + +Number.extend('random', function(min, max){ + return Math.floor(Math.random() * (max - min + 1) + min); +}); + +// forEach, each + +var hasOwnProperty = Object.prototype.hasOwnProperty; +Object.extend('forEach', function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object); + } +}); + +Object.each = Object.forEach; + +Array.implement({ + + forEach: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) fn.call(bind, this[i], i, this); + } + }, + + each: function(fn, bind){ + Array.forEach(this, fn, bind); + return this; + } + +}); + +// Array & Object cloning, Object merging and appending + +var cloneOf = function(item){ + switch (typeOf(item)){ + case 'array': return item.clone(); + case 'object': return Object.clone(item); + default: return item; + } +}; + +Array.implement('clone', function(){ + var i = this.length, clone = new Array(i); + while (i--) clone[i] = cloneOf(this[i]); + return clone; +}); + +var mergeOne = function(source, key, current){ + switch (typeOf(current)){ + case 'object': + if (typeOf(source[key]) == 'object') Object.merge(source[key], current); + else source[key] = Object.clone(current); + break; + case 'array': source[key] = current.clone(); break; + default: source[key] = current; + } + return source; +}; + +Object.extend({ + + merge: function(source, k, v){ + if (typeOf(k) == 'string') return mergeOne(source, k, v); + for (var i = 1, l = arguments.length; i < l; i++){ + var object = arguments[i]; + for (var key in object) mergeOne(source, key, object[key]); + } + return source; + }, + + clone: function(object){ + var clone = {}; + for (var key in object) clone[key] = cloneOf(object[key]); + return clone; + }, + + append: function(original){ + for (var i = 1, l = arguments.length; i < l; i++){ + var extended = arguments[i] || {}; + for (var key in extended) original[key] = extended[key]; + } + return original; + } + +}); + +// Object-less types + +['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){ + new Type(name); +}); + +// Unique ID + +var UID = Date.now(); + +String.extend('uniqueID', function(){ + return (UID++).toString(36); +}); + + + +})(); + + +/* +--- + +name: Array + +description: Contains Array Prototypes like each, contains, and erase. + +license: MIT-style license. + +requires: Type + +provides: Array + +... +*/ + +Array.implement({ + + /**/ + every: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && !fn.call(bind, this[i], i, this)) return false; + } + return true; + }, + + filter: function(fn, bind){ + var results = []; + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) results.push(this[i]); + } + return results; + }, + + indexOf: function(item, from){ + var len = this.length; + for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){ + if (this[i] === item) return i; + } + return -1; + }, + + map: function(fn, bind){ + var results = []; + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) results[i] = fn.call(bind, this[i], i, this); + } + return results; + }, + + some: function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++){ + if ((i in this) && fn.call(bind, this[i], i, this)) return true; + } + return false; + }, + /**/ + + clean: function(){ + return this.filter(function(item){ + return item != null; + }); + }, + + invoke: function(methodName){ + var args = Array.slice(arguments, 1); + return this.map(function(item){ + return item[methodName].apply(item, args); + }); + }, + + associate: function(keys){ + var obj = {}, length = Math.min(this.length, keys.length); + for (var i = 0; i < length; i++) obj[keys[i]] = this[i]; + return obj; + }, + + link: function(object){ + var result = {}; + for (var i = 0, l = this.length; i < l; i++){ + for (var key in object){ + if (object[key](this[i])){ + result[key] = this[i]; + delete object[key]; + break; + } + } + } + return result; + }, + + contains: function(item, from){ + return this.indexOf(item, from) != -1; + }, + + append: function(array){ + this.push.apply(this, array); + return this; + }, + + getLast: function(){ + return (this.length) ? this[this.length - 1] : null; + }, + + getRandom: function(){ + return (this.length) ? this[Number.random(0, this.length - 1)] : null; + }, + + include: function(item){ + if (!this.contains(item)) this.push(item); + return this; + }, + + combine: function(array){ + for (var i = 0, l = array.length; i < l; i++) this.include(array[i]); + return this; + }, + + erase: function(item){ + for (var i = this.length; i--;){ + if (this[i] === item) this.splice(i, 1); + } + return this; + }, + + empty: function(){ + this.length = 0; + return this; + }, + + flatten: function(){ + var array = []; + for (var i = 0, l = this.length; i < l; i++){ + var type = typeOf(this[i]); + if (type == 'null') continue; + array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]); + } + return array; + }, + + pick: function(){ + for (var i = 0, l = this.length; i < l; i++){ + if (this[i] != null) return this[i]; + } + return null; + }, + + hexToRgb: function(array){ + if (this.length != 3) return null; + var rgb = this.map(function(value){ + if (value.length == 1) value += value; + return value.toInt(16); + }); + return (array) ? rgb : 'rgb(' + rgb + ')'; + }, + + rgbToHex: function(array){ + if (this.length < 3) return null; + if (this.length == 4 && this[3] == 0 && !array) return 'transparent'; + var hex = []; + for (var i = 0; i < 3; i++){ + var bit = (this[i] - 0).toString(16); + hex.push((bit.length == 1) ? '0' + bit : bit); + } + return (array) ? hex : '#' + hex.join(''); + } + +}); + + + + +/* +--- + +name: String + +description: Contains String Prototypes like camelCase, capitalize, test, and toInt. + +license: MIT-style license. + +requires: Type + +provides: String + +... +*/ + +String.implement({ + + test: function(regex, params){ + return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this); + }, + + contains: function(string, separator){ + return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1; + }, + + trim: function(){ + return this.replace(/^\s+|\s+$/g, ''); + }, + + clean: function(){ + return this.replace(/\s+/g, ' ').trim(); + }, + + camelCase: function(){ + return this.replace(/-\D/g, function(match){ + return match.charAt(1).toUpperCase(); + }); + }, + + hyphenate: function(){ + return this.replace(/[A-Z]/g, function(match){ + return ('-' + match.charAt(0).toLowerCase()); + }); + }, + + capitalize: function(){ + return this.replace(/\b[a-z]/g, function(match){ + return match.toUpperCase(); + }); + }, + + escapeRegExp: function(){ + return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1'); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + hexToRgb: function(array){ + var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); + return (hex) ? hex.slice(1).hexToRgb(array) : null; + }, + + rgbToHex: function(array){ + var rgb = this.match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHex(array) : null; + }, + + substitute: function(object, regexp){ + return this.replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){ + if (match.charAt(0) == '\\') return match.slice(1); + return (object[name] != null) ? object[name] : ''; + }); + } + +}); + + +/* +--- + +name: Number + +description: Contains Number Prototypes like limit, round, times, and ceil. + +license: MIT-style license. + +requires: Type + +provides: Number + +... +*/ + +Number.implement({ + + limit: function(min, max){ + return Math.min(max, Math.max(min, this)); + }, + + round: function(precision){ + precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0); + return Math.round(this * precision) / precision; + }, + + times: function(fn, bind){ + for (var i = 0; i < this; i++) fn.call(bind, i, this); + }, + + toFloat: function(){ + return parseFloat(this); + }, + + toInt: function(base){ + return parseInt(this, base || 10); + } + +}); + +Number.alias('each', 'times'); + +(function(math){ + var methods = {}; + math.each(function(name){ + if (!Number[name]) methods[name] = function(){ + return Math[name].apply(null, [this].concat(Array.from(arguments))); + }; + }); + Number.implement(methods); +})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']); + + +/* +--- + +name: Function + +description: Contains Function Prototypes like create, bind, pass, and delay. + +license: MIT-style license. + +requires: Type + +provides: Function + +... +*/ + +Function.extend({ + + attempt: function(){ + for (var i = 0, l = arguments.length; i < l; i++){ + try { + return arguments[i](); + } catch (e){} + } + return null; + } + +}); + +Function.implement({ + + attempt: function(args, bind){ + try { + return this.apply(bind, Array.from(args)); + } catch (e){} + + return null; + }, + + /**/ + bind: function(bind){ + var self = this, + args = (arguments.length > 1) ? Array.slice(arguments, 1) : null; + + return function(){ + if (!args && !arguments.length) return self.call(bind); + if (args && arguments.length) return self.apply(bind, args.concat(Array.from(arguments))); + return self.apply(bind, args || arguments); + }; + }, + /**/ + + pass: function(args, bind){ + var self = this; + if (args != null) args = Array.from(args); + return function(){ + return self.apply(bind, args || arguments); + }; + }, + + delay: function(delay, bind, args){ + return setTimeout(this.pass((args == null ? [] : args), bind), delay); + }, + + periodical: function(periodical, bind, args){ + return setInterval(this.pass((args == null ? [] : args), bind), periodical); + } + +}); + + + + +/* +--- + +name: Object + +description: Object generic methods + +license: MIT-style license. + +requires: Type + +provides: [Object, Hash] + +... +*/ + +(function(){ + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +Object.extend({ + + subset: function(object, keys){ + var results = {}; + for (var i = 0, l = keys.length; i < l; i++){ + var k = keys[i]; + if (k in object) results[k] = object[k]; + } + return results; + }, + + map: function(object, fn, bind){ + var results = {}; + for (var key in object){ + if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object); + } + return results; + }, + + filter: function(object, fn, bind){ + var results = {}; + for (var key in object){ + var value = object[key]; + if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value; + } + return results; + }, + + every: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false; + } + return true; + }, + + some: function(object, fn, bind){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true; + } + return false; + }, + + keys: function(object){ + var keys = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) keys.push(key); + } + return keys; + }, + + values: function(object){ + var values = []; + for (var key in object){ + if (hasOwnProperty.call(object, key)) values.push(object[key]); + } + return values; + }, + + getLength: function(object){ + return Object.keys(object).length; + }, + + keyOf: function(object, value){ + for (var key in object){ + if (hasOwnProperty.call(object, key) && object[key] === value) return key; + } + return null; + }, + + contains: function(object, value){ + return Object.keyOf(object, value) != null; + }, + + toQueryString: function(object, base){ + var queryString = []; + + Object.each(object, function(value, key){ + if (base) key = base + '[' + key + ']'; + var result; + switch (typeOf(value)){ + case 'object': result = Object.toQueryString(value, key); break; + case 'array': + var qs = {}; + value.each(function(val, i){ + qs[i] = val; + }); + result = Object.toQueryString(qs, key); + break; + default: result = key + '=' + encodeURIComponent(value); + } + if (value != null) queryString.push(result); + }); + + return queryString.join('&'); + } + +}); + +})(); + + + + +/* +--- + +name: Browser + +description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash. + +license: MIT-style license. + +requires: [Array, Function, Number, String] + +provides: [Browser, Window, Document] + +... +*/ + +(function(){ + +var document = this.document; +var window = document.window = this; + +var UID = 1; + +this.$uid = (window.ActiveXObject) ? function(item){ + return (item.uid || (item.uid = [UID++]))[0]; +} : function(item){ + return item.uid || (item.uid = UID++); +}; + +$uid(window); +$uid(document); + +var ua = navigator.userAgent.toLowerCase(), + platform = navigator.platform.toLowerCase(), + UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0], + mode = UA[1] == 'ie' && document.documentMode; + +var Browser = this.Browser = { + + extend: Function.prototype.extend, + + name: (UA[1] == 'version') ? UA[3] : UA[1], + + version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]), + + Platform: { + name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0] + }, + + Features: { + xpath: !!(document.evaluate), + air: !!(window.runtime), + query: !!(document.querySelector), + json: !!(window.JSON) + }, + + Plugins: {} + +}; + +Browser[Browser.name] = true; +Browser[Browser.name + parseInt(Browser.version, 10)] = true; +Browser.Platform[Browser.Platform.name] = true; + +// Request + +Browser.Request = (function(){ + + var XMLHTTP = function(){ + return new XMLHttpRequest(); + }; + + var MSXML2 = function(){ + return new ActiveXObject('MSXML2.XMLHTTP'); + }; + + var MSXML = function(){ + return new ActiveXObject('Microsoft.XMLHTTP'); + }; + + return Function.attempt(function(){ + XMLHTTP(); + return XMLHTTP; + }, function(){ + MSXML2(); + return MSXML2; + }, function(){ + MSXML(); + return MSXML; + }); + +})(); + +Browser.Features.xhr = !!(Browser.Request); + +// Flash detection + +var version = (Function.attempt(function(){ + return navigator.plugins['Shockwave Flash'].description; +}, function(){ + return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); +}) || '0 r0').match(/\d+/g); + +Browser.Plugins.Flash = { + version: Number(version[0] || '0.' + version[1]) || 0, + build: Number(version[2]) || 0 +}; + +// String scripts + +Browser.exec = function(text){ + if (!text) return text; + if (window.execScript){ + window.execScript(text); + } else { + var script = document.createElement('script'); + script.setAttribute('type', 'text/javascript'); + script.text = text; + document.head.appendChild(script); + document.head.removeChild(script); + } + return text; +}; + +String.implement('stripScripts', function(exec){ + var scripts = ''; + var text = this.replace(/]*>([\s\S]*?)<\/script>/gi, function(all, code){ + scripts += code + '\n'; + return ''; + }); + if (exec === true) Browser.exec(scripts); + else if (typeOf(exec) == 'function') exec(scripts, text); + return text; +}); + +// Window, Document + +Browser.extend({ + Document: this.Document, + Window: this.Window, + Element: this.Element, + Event: this.Event +}); + +this.Window = this.$constructor = new Type('Window', function(){}); + +this.$family = Function.from('window').hide(); + +Window.mirror(function(name, method){ + window[name] = method; +}); + +this.Document = document.$constructor = new Type('Document', function(){}); + +document.$family = Function.from('document').hide(); + +Document.mirror(function(name, method){ + document[name] = method; +}); + +document.html = document.documentElement; +if (!document.head) document.head = document.getElementsByTagName('head')[0]; + +if (document.execCommand) try { + document.execCommand("BackgroundImageCache", false, true); +} catch (e){} + +/**/ +if (this.attachEvent && !this.addEventListener){ + var unloadEvent = function(){ + this.detachEvent('onunload', unloadEvent); + document.head = document.html = document.window = null; + }; + this.attachEvent('onunload', unloadEvent); +} + +// IE fails on collections and ) +var arrayFrom = Array.from; +try { + arrayFrom(document.html.childNodes); +} catch(e){ + Array.from = function(item){ + if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){ + var i = item.length, array = new Array(i); + while (i--) array[i] = item[i]; + return array; + } + return arrayFrom(item); + }; + + var prototype = Array.prototype, + slice = prototype.slice; + ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){ + var method = prototype[name]; + Array[name] = function(item){ + return method.apply(Array.from(item), slice.call(arguments, 1)); + }; + }); +} +/**/ + + + +})(); + + +/* +--- + +name: Event + +description: Contains the Event Class, to make the event object cross-browser. + +license: MIT-style license. + +requires: [Window, Document, Array, Function, String, Object] + +provides: Event + +... +*/ + +var Event = new Type('Event', function(event, win){ + if (!win) win = window; + var doc = win.document; + event = event || win.event; + if (event.$extended) return event; + this.$extended = true; + var type = event.type, + target = event.target || event.srcElement, + page = {}, + client = {}, + related = null, + rightClick, wheel, code, key; + while (target && target.nodeType == 3) target = target.parentNode; + + if (type.indexOf('key') != -1){ + code = event.which || event.keyCode; + key = Object.keyOf(Event.Keys, code); + if (type == 'keydown'){ + var fKey = code - 111; + if (fKey > 0 && fKey < 13) key = 'f' + fKey; + } + if (!key) key = String.fromCharCode(code).toLowerCase(); + } else if ((/click|mouse|menu/i).test(type)){ + doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; + page = { + x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft, + y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop + }; + client = { + x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX, + y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY + }; + if ((/DOMMouseScroll|mousewheel/).test(type)){ + wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3; + } + rightClick = (event.which == 3) || (event.button == 2); + if ((/over|out/).test(type)){ + related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element']; + var testRelated = function(){ + while (related && related.nodeType == 3) related = related.parentNode; + return true; + }; + var hasRelated = (Browser.firefox2) ? testRelated.attempt() : testRelated(); + related = (hasRelated) ? related : null; + } + } else if ((/gesture|touch/i).test(type)){ + this.rotation = event.rotation; + this.scale = event.scale; + this.targetTouches = event.targetTouches; + this.changedTouches = event.changedTouches; + var touches = this.touches = event.touches; + if (touches && touches[0]){ + var touch = touches[0]; + page = {x: touch.pageX, y: touch.pageY}; + client = {x: touch.clientX, y: touch.clientY}; + } + } + + return Object.append(this, { + event: event, + type: type, + + page: page, + client: client, + rightClick: rightClick, + + wheel: wheel, + + relatedTarget: document.id(related), + target: document.id(target), + + code: code, + key: key, + + shift: event.shiftKey, + control: event.ctrlKey, + alt: event.altKey, + meta: event.metaKey + }); +}); + +Event.Keys = { + 'enter': 13, + 'up': 38, + 'down': 40, + 'left': 37, + 'right': 39, + 'esc': 27, + 'space': 32, + 'backspace': 8, + 'tab': 9, + 'delete': 46 +}; + + + +Event.implement({ + + stop: function(){ + return this.stopPropagation().preventDefault(); + }, + + stopPropagation: function(){ + if (this.event.stopPropagation) this.event.stopPropagation(); + else this.event.cancelBubble = true; + return this; + }, + + preventDefault: function(){ + if (this.event.preventDefault) this.event.preventDefault(); + else this.event.returnValue = false; + return this; + } + +}); + + +/* +--- + +name: Class + +description: Contains the Class Function for easily creating, extending, and implementing reusable Classes. + +license: MIT-style license. + +requires: [Array, String, Function, Number] + +provides: Class + +... +*/ + +(function(){ + +var Class = this.Class = new Type('Class', function(params){ + if (instanceOf(params, Function)) params = {initialize: params}; + + var newClass = function(){ + reset(this); + if (newClass.$prototyping) return this; + this.$caller = null; + var value = (this.initialize) ? this.initialize.apply(this, arguments) : this; + this.$caller = this.caller = null; + return value; + }.extend(this).implement(params); + + newClass.$constructor = Class; + newClass.prototype.$constructor = newClass; + newClass.prototype.parent = parent; + + return newClass; +}); + +var parent = function(){ + if (!this.$caller) throw new Error('The method "parent" cannot be called.'); + var name = this.$caller.$name, + parent = this.$caller.$owner.parent, + previous = (parent) ? parent.prototype[name] : null; + if (!previous) throw new Error('The method "' + name + '" has no parent.'); + return previous.apply(this, arguments); +}; + +var reset = function(object){ + for (var key in object){ + var value = object[key]; + switch (typeOf(value)){ + case 'object': + var F = function(){}; + F.prototype = value; + object[key] = reset(new F); + break; + case 'array': object[key] = value.clone(); break; + } + } + return object; +}; + +var wrap = function(self, key, method){ + if (method.$origin) method = method.$origin; + var wrapper = function(){ + if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.'); + var caller = this.caller, current = this.$caller; + this.caller = current; this.$caller = wrapper; + var result = method.apply(this, arguments); + this.$caller = current; this.caller = caller; + return result; + }.extend({$owner: self, $origin: method, $name: key}); + return wrapper; +}; + +var implement = function(key, value, retain){ + if (Class.Mutators.hasOwnProperty(key)){ + value = Class.Mutators[key].call(this, value); + if (value == null) return this; + } + + if (typeOf(value) == 'function'){ + if (value.$hidden) return this; + this.prototype[key] = (retain) ? value : wrap(this, key, value); + } else { + Object.merge(this.prototype, key, value); + } + + return this; +}; + +var getInstance = function(klass){ + klass.$prototyping = true; + var proto = new klass; + delete klass.$prototyping; + return proto; +}; + +Class.implement('implement', implement.overloadSetter()); + +Class.Mutators = { + + Extends: function(parent){ + this.parent = parent; + this.prototype = getInstance(parent); + }, + + Implements: function(items){ + Array.from(items).each(function(item){ + var instance = new item; + for (var key in instance) implement.call(this, key, instance[key], true); + }, this); + } +}; + +})(); + + +/* +--- + +name: Class.Extras + +description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks. + +license: MIT-style license. + +requires: Class + +provides: [Class.Extras, Chain, Events, Options] + +... +*/ + +(function(){ + +this.Chain = new Class({ + + $chain: [], + + chain: function(){ + this.$chain.append(Array.flatten(arguments)); + return this; + }, + + callChain: function(){ + return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false; + }, + + clearChain: function(){ + this.$chain.empty(); + return this; + } + +}); + +var removeOn = function(string){ + return string.replace(/^on([A-Z])/, function(full, first){ + return first.toLowerCase(); + }); +}; + +this.Events = new Class({ + + $events: {}, + + addEvent: function(type, fn, internal){ + type = removeOn(type); + + + + this.$events[type] = (this.$events[type] || []).include(fn); + if (internal) fn.internal = true; + return this; + }, + + addEvents: function(events){ + for (var type in events) this.addEvent(type, events[type]); + return this; + }, + + fireEvent: function(type, args, delay){ + type = removeOn(type); + var events = this.$events[type]; + if (!events) return this; + args = Array.from(args); + events.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + removeEvent: function(type, fn){ + type = removeOn(type); + var events = this.$events[type]; + if (events && !fn.internal){ + var index = events.indexOf(fn); + if (index != -1) delete events[index]; + } + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + if (events) events = removeOn(events); + for (type in this.$events){ + if (events && events != type) continue; + var fns = this.$events[type]; + for (var i = fns.length; i--;) if (i in fns){ + this.removeEvent(type, fns[i]); + } + } + return this; + } + +}); + +this.Options = new Class({ + + setOptions: function(){ + var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments)); + if (this.addEvent) for (var option in options){ + if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue; + this.addEvent(option, options[option]); + delete options[option]; + } + return this; + } + +}); + +})(); + + +/* +--- +name: Slick.Parser +description: Standalone CSS3 Selector parser +provides: Slick.Parser +... +*/ + +;(function(){ + +var parsed, + separatorIndex, + combinatorIndex, + reversed, + cache = {}, + reverseCache = {}, + reUnescape = /\\/g; + +var parse = function(expression, isReversed){ + if (expression == null) return null; + if (expression.Slick === true) return expression; + expression = ('' + expression).replace(/^\s+|\s+$/g, ''); + reversed = !!isReversed; + var currentCache = (reversed) ? reverseCache : cache; + if (currentCache[expression]) return currentCache[expression]; + parsed = { + Slick: true, + expressions: [], + raw: expression, + reverse: function(){ + return parse(this.raw, true); + } + }; + separatorIndex = -1; + while (expression != (expression = expression.replace(regexp, parser))); + parsed.length = parsed.expressions.length; + return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed; +}; + +var reverseCombinator = function(combinator){ + if (combinator === '!') return ' '; + else if (combinator === ' ') return '!'; + else if ((/^!/).test(combinator)) return combinator.replace(/^!/, ''); + else return '!' + combinator; +}; + +var reverse = function(expression){ + var expressions = expression.expressions; + for (var i = 0; i < expressions.length; i++){ + var exp = expressions[i]; + var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)}; + + for (var j = 0; j < exp.length; j++){ + var cexp = exp[j]; + if (!cexp.reverseCombinator) cexp.reverseCombinator = ' '; + cexp.combinator = cexp.reverseCombinator; + delete cexp.reverseCombinator; + } + + exp.reverse().push(last); + } + return expression; +}; + +var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan MIT License + return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){ + return '\\' + match; + }); +}; + +var regexp = new RegExp( +/* +#!/usr/bin/env ruby +puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'') +__END__ + "(?x)^(?:\ + \\s* ( , ) \\s* # Separator \n\ + | \\s* ( + ) \\s* # Combinator \n\ + | ( \\s+ ) # CombinatorChildren \n\ + | ( + | \\* ) # Tag \n\ + | \\# ( + ) # ID \n\ + | \\. ( + ) # ClassName \n\ + | # Attribute \n\ + \\[ \ + \\s* (+) (?: \ + \\s* ([*^$!~|]?=) (?: \ + \\s* (?:\ + ([\"']?)(.*?)\\9 \ + )\ + ) \ + )? \\s* \ + \\](?!\\]) \n\ + | :+ ( + )(?:\ + \\( (?:\ + (?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\ + ) \\)\ + )?\ + )" +*/ + "^(?:\\s*(,)\\s*|\\s*(+)\\s*|(\\s+)|(+|\\*)|\\#(+)|\\.(+)|\\[\\s*(+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)" + .replace(//, '[' + escapeRegExp(">+~`!@$%^&={}\\;/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') + .replace(//g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])') +); + +function parser( + rawMatch, + + separator, + combinator, + combinatorChildren, + + tagName, + id, + className, + + attributeKey, + attributeOperator, + attributeQuote, + attributeValue, + + pseudoMarker, + pseudoClass, + pseudoQuote, + pseudoClassQuotedValue, + pseudoClassValue +){ + if (separator || separatorIndex === -1){ + parsed.expressions[++separatorIndex] = []; + combinatorIndex = -1; + if (separator) return ''; + } + + if (combinator || combinatorChildren || combinatorIndex === -1){ + combinator = combinator || ' '; + var currentSeparator = parsed.expressions[separatorIndex]; + if (reversed && currentSeparator[combinatorIndex]) + currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator); + currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'}; + } + + var currentParsed = parsed.expressions[separatorIndex][combinatorIndex]; + + if (tagName){ + currentParsed.tag = tagName.replace(reUnescape, ''); + + } else if (id){ + currentParsed.id = id.replace(reUnescape, ''); + + } else if (className){ + className = className.replace(reUnescape, ''); + + if (!currentParsed.classList) currentParsed.classList = []; + if (!currentParsed.classes) currentParsed.classes = []; + currentParsed.classList.push(className); + currentParsed.classes.push({ + value: className, + regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)') + }); + + } else if (pseudoClass){ + pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue; + pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null; + + if (!currentParsed.pseudos) currentParsed.pseudos = []; + currentParsed.pseudos.push({ + key: pseudoClass.replace(reUnescape, ''), + value: pseudoClassValue, + type: pseudoMarker.length == 1 ? 'class' : 'element' + }); + + } else if (attributeKey){ + attributeKey = attributeKey.replace(reUnescape, ''); + attributeValue = (attributeValue || '').replace(reUnescape, ''); + + var test, regexp; + + switch (attributeOperator){ + case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break; + case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break; + case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break; + case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break; + case '=' : test = function(value){ + return attributeValue == value; + }; break; + case '*=' : test = function(value){ + return value && value.indexOf(attributeValue) > -1; + }; break; + case '!=' : test = function(value){ + return attributeValue != value; + }; break; + default : test = function(value){ + return !!value; + }; + } + + if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){ + return false; + }; + + if (!test) test = function(value){ + return value && regexp.test(value); + }; + + if (!currentParsed.attributes) currentParsed.attributes = []; + currentParsed.attributes.push({ + key: attributeKey, + operator: attributeOperator, + value: attributeValue, + test: test + }); + + } + + return ''; +}; + +// Slick NS + +var Slick = (this.Slick || {}); + +Slick.parse = function(expression){ + return parse(expression); +}; + +Slick.escapeRegExp = escapeRegExp; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/**/(typeof exports != 'undefined') ? exports : /**/this); + + +/* +--- +name: Slick.Finder +description: The new, superfast css selector engine. +provides: Slick.Finder +requires: Slick.Parser +... +*/ + +;(function(){ + +var local = {}, + featuresCache = {}, + toString = Object.prototype.toString; + +// Feature / Bug detection + +local.isNativeCode = function(fn){ + return (/\{\s*\[native code\]\s*\}/).test('' + fn); +}; + +local.isXML = function(document){ + return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') || + (document.nodeType == 9 && document.documentElement.nodeName != 'HTML'); +}; + +local.setDocument = function(document){ + + // convert elements / window arguments to document. if document cannot be extrapolated, the function returns. + var nodeType = document.nodeType; + if (nodeType == 9); // document + else if (nodeType) document = document.ownerDocument; // node + else if (document.navigator) document = document.document; // window + else return; + + // check if it's the old document + + if (this.document === document) return; + this.document = document; + + // check if we have done feature detection on this document before + + var root = document.documentElement, + rootUid = this.getUIDXML(root), + features = featuresCache[rootUid], + feature; + + if (features){ + for (feature in features){ + this[feature] = features[feature]; + } + return; + } + + features = featuresCache[rootUid] = {}; + + features.root = root; + features.isXMLDocument = this.isXML(document); + + features.brokenStarGEBTN + = features.starSelectsClosedQSA + = features.idGetsName + = features.brokenMixedCaseQSA + = features.brokenGEBCN + = features.brokenCheckedQSA + = features.brokenEmptyAttributeQSA + = features.isHTMLDocument + = features.nativeMatchesSelector + = false; + + var starSelectsClosed, starSelectsComments, + brokenSecondClassNameGEBCN, cachedGetElementsByClassName, + brokenFormAttributeGetter; + + var selected, id = 'slick_uniqueid'; + var testNode = document.createElement('div'); + + var testRoot = document.body || document.getElementsByTagName('body')[0] || root; + testRoot.appendChild(testNode); + + // on non-HTML documents innerHTML and getElementsById doesnt work properly + try { + testNode.innerHTML = ''; + features.isHTMLDocument = !!document.getElementById(id); + } catch(e){}; + + if (features.isHTMLDocument){ + + testNode.style.display = 'none'; + + // IE returns comment nodes for getElementsByTagName('*') for some documents + testNode.appendChild(document.createComment('')); + starSelectsComments = (testNode.getElementsByTagName('*').length > 1); + + // IE returns closed nodes (EG:"") for getElementsByTagName('*') for some documents + try { + testNode.innerHTML = 'foo'; + selected = testNode.getElementsByTagName('*'); + starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + features.brokenStarGEBTN = starSelectsComments || starSelectsClosed; + + // IE returns elements with the name instead of just id for getElementsById for some documents + try { + testNode.innerHTML = ''; + features.idGetsName = document.getElementById(id) === testNode.firstChild; + } catch(e){}; + + if (testNode.getElementsByClassName){ + + // Safari 3.2 getElementsByClassName caches results + try { + testNode.innerHTML = ''; + testNode.getElementsByClassName('b').length; + testNode.firstChild.className = 'b'; + cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2); + } catch(e){}; + + // Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one + try { + testNode.innerHTML = ''; + brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2); + } catch(e){}; + + features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN; + } + + if (testNode.querySelectorAll){ + // IE 8 returns closed nodes (EG:"") for querySelectorAll('*') for some documents + try { + testNode.innerHTML = 'foo'; + selected = testNode.querySelectorAll('*'); + features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/'); + } catch(e){}; + + // Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode + try { + testNode.innerHTML = ''; + features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length; + } catch(e){}; + + // Webkit and Opera dont return selected options on querySelectorAll + try { + testNode.innerHTML = ''; + features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0); + } catch(e){}; + + // IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll + try { + testNode.innerHTML = ''; + features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0); + } catch(e){}; + + } + + // IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input + try { + testNode.innerHTML = '
'; + brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's'); + } catch(e){}; + + // native matchesSelector function + + features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector; + if (features.nativeMatchesSelector) try { + // if matchesSelector trows errors on incorrect sintaxes we can use it + features.nativeMatchesSelector.call(root, ':slick'); + features.nativeMatchesSelector = null; + } catch(e){}; + + } + + try { + root.slick_expando = 1; + delete root.slick_expando; + features.getUID = this.getUIDHTML; + } catch(e) { + features.getUID = this.getUIDXML; + } + + testRoot.removeChild(testNode); + testNode = selected = testRoot = null; + + // getAttribute + + features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){ + var method = this.attributeGetters[name]; + if (method) return method.call(node); + var attributeNode = node.getAttributeNode(name); + return (attributeNode) ? attributeNode.nodeValue : null; + } : function(node, name){ + var method = this.attributeGetters[name]; + return (method) ? method.call(node) : node.getAttribute(name); + }; + + // hasAttribute + + features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) { + return node.hasAttribute(attribute); + } : function(node, attribute) { + node = node.getAttributeNode(attribute); + return !!(node && (node.specified || node.nodeValue)); + }; + + // contains + // FIXME: Add specs: local.contains should be different for xml and html documents? + features.contains = (root && this.isNativeCode(root.contains)) ? function(context, node){ + return context.contains(node); + } : (root && root.compareDocumentPosition) ? function(context, node){ + return context === node || !!(context.compareDocumentPosition(node) & 16); + } : function(context, node){ + if (node) do { + if (node === context) return true; + } while ((node = node.parentNode)); + return false; + }; + + // document order sorting + // credits to Sizzle (http://sizzlejs.com/) + + features.documentSorter = (root.compareDocumentPosition) ? function(a, b){ + if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0; + return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1; + } : ('sourceIndex' in root) ? function(a, b){ + if (!a.sourceIndex || !b.sourceIndex) return 0; + return a.sourceIndex - b.sourceIndex; + } : (document.createRange) ? function(a, b){ + if (!a.ownerDocument || !b.ownerDocument) return 0; + var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange(); + aRange.setStart(a, 0); + aRange.setEnd(a, 0); + bRange.setStart(b, 0); + bRange.setEnd(b, 0); + return aRange.compareBoundaryPoints(Range.START_TO_END, bRange); + } : null ; + + root = null; + + for (feature in features){ + this[feature] = features[feature]; + } +}; + +// Main Method + +var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/, + reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/, + qsaFailExpCache = {}; + +local.search = function(context, expression, append, first){ + + var found = this.found = (first) ? null : (append || []); + + if (!context) return found; + else if (context.navigator) context = context.document; // Convert the node from a window to a document + else if (!context.nodeType) return found; + + // setup + + var parsed, i, + uniques = this.uniques = {}, + hasOthers = !!(append && append.length), + contextIsDocument = (context.nodeType == 9); + + if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context); + + // avoid duplicating items already in the append array + if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true; + + // expression checks + + if (typeof expression == 'string'){ // expression is a string + + /**/ + var simpleSelector = expression.match(reSimpleSelector); + simpleSelectors: if (simpleSelector) { + + var symbol = simpleSelector[1], + name = simpleSelector[2], + node, nodes; + + if (!symbol){ + + if (name == '*' && this.brokenStarGEBTN) break simpleSelectors; + nodes = context.getElementsByTagName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + } else if (symbol == '#'){ + + if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors; + node = context.getElementById(name); + if (!node) return found; + if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors; + if (first) return node || null; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + + } else if (symbol == '.'){ + + if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors; + if (context.getElementsByClassName && !this.brokenGEBCN){ + nodes = context.getElementsByClassName(name); + if (first) return nodes[0] || null; + for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } else { + var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)'); + nodes = context.getElementsByTagName('*'); + for (i = 0; node = nodes[i++];){ + className = node.className; + if (!(className && matchClass.test(className))) continue; + if (first) return node; + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + } + + } + + if (hasOthers) this.sort(found); + return (first) ? null : found; + + } + /**/ + + /**/ + querySelector: if (context.querySelectorAll) { + + if (!this.isHTMLDocument + || qsaFailExpCache[expression] + //TODO: only skip when expression is actually mixed case + || this.brokenMixedCaseQSA + || (this.brokenCheckedQSA && expression.indexOf(':checked') > -1) + || (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression)) + || (!contextIsDocument //Abort when !contextIsDocument and... + // there are multiple expressions in the selector + // since we currently only fix non-document rooted QSA for single expression selectors + && expression.indexOf(',') > -1 + ) + || Slick.disableQSA + ) break querySelector; + + var _expression = expression, _context = context; + if (!contextIsDocument){ + // non-document rooted QSA + // credits to Andrew Dupont + var currentId = _context.getAttribute('id'), slickid = 'slickid__'; + _context.setAttribute('id', slickid); + _expression = '#' + slickid + ' ' + _expression; + context = _context.parentNode; + } + + try { + if (first) return context.querySelector(_expression) || null; + else nodes = context.querySelectorAll(_expression); + } catch(e) { + qsaFailExpCache[expression] = 1; + break querySelector; + } finally { + if (!contextIsDocument){ + if (currentId) _context.setAttribute('id', currentId); + else _context.removeAttribute('id'); + context = _context; + } + } + + if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){ + if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node); + } else for (i = 0; node = nodes[i++];){ + if (!(hasOthers && uniques[this.getUID(node)])) found.push(node); + } + + if (hasOthers) this.sort(found); + return found; + + } + /**/ + + parsed = this.Slick.parse(expression); + if (!parsed.length) return found; + } else if (expression == null){ // there is no expression + return found; + } else if (expression.Slick){ // expression is a parsed Slick object + parsed = expression; + } else if (this.contains(context.documentElement || context, expression)){ // expression is a node + (found) ? found.push(expression) : found = expression; + return found; + } else { // other junk + return found; + } + + /**//**/ + + // cache elements for the nth selectors + + this.posNTH = {}; + this.posNTHLast = {}; + this.posNTHType = {}; + this.posNTHTypeLast = {}; + + /**//**/ + + // if append is null and there is only a single selector with one expression use pushArray, else use pushUID + this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID; + + if (found == null) found = []; + + // default engine + + var j, m, n; + var combinator, tag, id, classList, classes, attributes, pseudos; + var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions; + + search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){ + + combinator = 'combinator:' + currentBit.combinator; + if (!this[combinator]) continue search; + + tag = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase(); + id = currentBit.id; + classList = currentBit.classList; + classes = currentBit.classes; + attributes = currentBit.attributes; + pseudos = currentBit.pseudos; + lastBit = (j === (currentExpression.length - 1)); + + this.bitUniques = {}; + + if (lastBit){ + this.uniques = uniques; + this.found = found; + } else { + this.uniques = {}; + this.found = []; + } + + if (j === 0){ + this[combinator](context, tag, id, classes, attributes, pseudos, classList); + if (first && lastBit && found.length) break search; + } else { + if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){ + this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + if (found.length) break search; + } else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList); + } + + currentItems = this.found; + } + + // should sort if there are nodes in append and if you pass multiple expressions. + if (hasOthers || (parsed.expressions.length > 1)) this.sort(found); + + return (first) ? (found[0] || null) : found; +}; + +// Utils + +local.uidx = 1; +local.uidk = 'slick-uniqueid'; + +local.getUIDXML = function(node){ + var uid = node.getAttribute(this.uidk); + if (!uid){ + uid = this.uidx++; + node.setAttribute(this.uidk, uid); + } + return uid; +}; + +local.getUIDHTML = function(node){ + return node.uniqueNumber || (node.uniqueNumber = this.uidx++); +}; + +// sort based on the setDocument documentSorter method. + +local.sort = function(results){ + if (!this.documentSorter) return results; + results.sort(this.documentSorter); + return results; +}; + +/**//**/ + +local.cacheNTH = {}; + +local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/; + +local.parseNTHArgument = function(argument){ + var parsed = argument.match(this.matchNTH); + if (!parsed) return false; + var special = parsed[2] || false; + var a = parsed[1] || 1; + if (a == '-') a = -1; + var b = +parsed[3] || 0; + parsed = + (special == 'n') ? {a: a, b: b} : + (special == 'odd') ? {a: 2, b: 1} : + (special == 'even') ? {a: 2, b: 0} : {a: 0, b: a}; + + return (this.cacheNTH[argument] = parsed); +}; + +local.createNTHPseudo = function(child, sibling, positions, ofType){ + return function(node, argument){ + var uid = this.getUID(node); + if (!this[positions][uid]){ + var parent = node.parentNode; + if (!parent) return false; + var el = parent[child], count = 1; + if (ofType){ + var nodeName = node.nodeName; + do { + if (el.nodeName != nodeName) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } else { + do { + if (el.nodeType != 1) continue; + this[positions][this.getUID(el)] = count++; + } while ((el = el[sibling])); + } + } + argument = argument || 'n'; + var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument); + if (!parsed) return false; + var a = parsed.a, b = parsed.b, pos = this[positions][uid]; + if (a == 0) return b == pos; + if (a > 0){ + if (pos < b) return false; + } else { + if (b < pos) return false; + } + return ((pos - b) % a) == 0; + }; +}; + +/**//**/ + +local.pushArray = function(node, tag, id, classes, attributes, pseudos){ + if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node); +}; + +local.pushUID = function(node, tag, id, classes, attributes, pseudos){ + var uid = this.getUID(node); + if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){ + this.uniques[uid] = true; + this.found.push(node); + } +}; + +local.matchNode = function(node, selector){ + if (this.isHTMLDocument && this.nativeMatchesSelector){ + try { + return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]')); + } catch(matchError) {} + } + + var parsed = this.Slick.parse(selector); + if (!parsed) return true; + + // simple (single) selectors + var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i; + for (i = 0; (currentExpression = expressions[i]); i++){ + if (currentExpression.length == 1){ + var exp = currentExpression[0]; + if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true; + simpleExpCounter++; + } + } + + if (simpleExpCounter == parsed.length) return false; + + var nodes = this.search(this.document, parsed), item; + for (i = 0; item = nodes[i++];){ + if (item === node) return true; + } + return false; +}; + +local.matchPseudo = function(node, name, argument){ + var pseudoName = 'pseudo:' + name; + if (this[pseudoName]) return this[pseudoName](node, argument); + var attribute = this.getAttribute(node, name); + return (argument) ? argument == attribute : !!attribute; +}; + +local.matchSelector = function(node, tag, id, classes, attributes, pseudos){ + if (tag){ + var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase(); + if (tag == '*'){ + if (nodeName < '@') return false; // Fix for comment nodes and closed nodes + } else { + if (nodeName != tag) return false; + } + } + + if (id && node.getAttribute('id') != id) return false; + + var i, part, cls; + if (classes) for (i = classes.length; i--;){ + cls = node.getAttribute('class') || node.className; + if (!(cls && classes[i].regexp.test(cls))) return false; + } + if (attributes) for (i = attributes.length; i--;){ + part = attributes[i]; + if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false; + } + if (pseudos) for (i = pseudos.length; i--;){ + part = pseudos[i]; + if (!this.matchPseudo(node, part.key, part.value)) return false; + } + return true; +}; + +var combinators = { + + ' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level + + var i, item, children; + + if (this.isHTMLDocument){ + getById: if (id){ + item = this.document.getElementById(id); + if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){ + // all[id] returns all the elements with that name or id inside node + // if theres just one it will return the element, else it will be a collection + children = node.all[id]; + if (!children) return; + if (!children[0]) children = [children]; + for (i = 0; item = children[i++];){ + var idNode = item.getAttributeNode('id'); + if (idNode && idNode.nodeValue == id){ + this.push(item, tag, null, classes, attributes, pseudos); + break; + } + } + return; + } + if (!item){ + // if the context is in the dom we return, else we will try GEBTN, breaking the getById label + if (this.contains(this.root, node)) return; + else break getById; + } else if (this.document !== node && !this.contains(node, item)) return; + this.push(item, tag, null, classes, attributes, pseudos); + return; + } + getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){ + children = node.getElementsByClassName(classList.join(' ')); + if (!(children && children.length)) break getByClass; + for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos); + return; + } + } + getByTag: { + children = node.getElementsByTagName(tag); + if (!(children && children.length)) break getByTag; + if (!this.brokenStarGEBTN) tag = null; + for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos); + } + }, + + '>': function(node, tag, id, classes, attributes, pseudos){ // direct children + if ((node = node.firstChild)) do { + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + } while ((node = node.nextSibling)); + }, + + '+': function(node, tag, id, classes, attributes, pseudos){ // next sibling + while ((node = node.nextSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '^': function(node, tag, id, classes, attributes, pseudos){ // first child + node = node.firstChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '~': function(node, tag, id, classes, attributes, pseudos){ // next siblings + while ((node = node.nextSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + }, + + '++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling + this['combinator:+'](node, tag, id, classes, attributes, pseudos); + this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + }, + + '~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings + this['combinator:~'](node, tag, id, classes, attributes, pseudos); + this['combinator:!~'](node, tag, id, classes, attributes, pseudos); + }, + + '!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document + while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level) + node = node.parentNode; + if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos); + }, + + '!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling + while ((node = node.previousSibling)) if (node.nodeType == 1){ + this.push(node, tag, id, classes, attributes, pseudos); + break; + } + }, + + '!^': function(node, tag, id, classes, attributes, pseudos){ // last child + node = node.lastChild; + if (node){ + if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos); + else this['combinator:!+'](node, tag, id, classes, attributes, pseudos); + } + }, + + '!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings + while ((node = node.previousSibling)){ + if (node.nodeType != 1) continue; + var uid = this.getUID(node); + if (this.bitUniques[uid]) break; + this.bitUniques[uid] = true; + this.push(node, tag, id, classes, attributes, pseudos); + } + } + +}; + +for (var c in combinators) local['combinator:' + c] = combinators[c]; + +var pseudos = { + + /**/ + + 'empty': function(node){ + var child = node.firstChild; + return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length; + }, + + 'not': function(node, expression){ + return !this.matchNode(node, expression); + }, + + 'contains': function(node, text){ + return (node.innerText || node.textContent || '').indexOf(text) > -1; + }, + + 'first-child': function(node){ + while ((node = node.previousSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'last-child': function(node){ + while ((node = node.nextSibling)) if (node.nodeType == 1) return false; + return true; + }, + + 'only-child': function(node){ + var prev = node; + while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeType == 1) return false; + return true; + }, + + /**/ + + 'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'), + + 'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'), + + 'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true), + + 'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true), + + 'index': function(node, index){ + return this['pseudo:nth-child'](node, '' + index + 1); + }, + + 'even': function(node){ + return this['pseudo:nth-child'](node, '2n'); + }, + + 'odd': function(node){ + return this['pseudo:nth-child'](node, '2n+1'); + }, + + /**/ + + /**/ + + 'first-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'last-of-type': function(node){ + var nodeName = node.nodeName; + while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false; + return true; + }, + + 'only-of-type': function(node){ + var prev = node, nodeName = node.nodeName; + while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false; + var next = node; + while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false; + return true; + }, + + /**/ + + // custom pseudos + + 'enabled': function(node){ + return !node.disabled; + }, + + 'disabled': function(node){ + return node.disabled; + }, + + 'checked': function(node){ + return node.checked || node.selected; + }, + + 'focus': function(node){ + return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex')); + }, + + 'root': function(node){ + return (node === this.root); + }, + + 'selected': function(node){ + return node.selected; + } + + /**/ +}; + +for (var p in pseudos) local['pseudo:' + p] = pseudos[p]; + +// attributes methods + +local.attributeGetters = { + + 'class': function(){ + return this.getAttribute('class') || this.className; + }, + + 'for': function(){ + return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for'); + }, + + 'href': function(){ + return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href'); + }, + + 'style': function(){ + return (this.style) ? this.style.cssText : this.getAttribute('style'); + }, + + 'tabindex': function(){ + var attributeNode = this.getAttributeNode('tabindex'); + return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null; + }, + + 'type': function(){ + return this.getAttribute('type'); + } + +}; + +// Slick + +var Slick = local.Slick = (this.Slick || {}); + +Slick.version = '1.1.5'; + +// Slick finder + +Slick.search = function(context, expression, append){ + return local.search(context, expression, append); +}; + +Slick.find = function(context, expression){ + return local.search(context, expression, null, true); +}; + +// Slick containment checker + +Slick.contains = function(container, node){ + local.setDocument(container); + return local.contains(container, node); +}; + +// Slick attribute getter + +Slick.getAttribute = function(node, name){ + return local.getAttribute(node, name); +}; + +// Slick matcher + +Slick.match = function(node, selector){ + if (!(node && selector)) return false; + if (!selector || selector === node) return true; + local.setDocument(node); + return local.matchNode(node, selector); +}; + +// Slick attribute accessor + +Slick.defineAttributeGetter = function(name, fn){ + local.attributeGetters[name] = fn; + return this; +}; + +Slick.lookupAttributeGetter = function(name){ + return local.attributeGetters[name]; +}; + +// Slick pseudo accessor + +Slick.definePseudo = function(name, fn){ + local['pseudo:' + name] = function(node, argument){ + return fn.call(node, argument); + }; + return this; +}; + +Slick.lookupPseudo = function(name){ + var pseudo = local['pseudo:' + name]; + if (pseudo) return function(argument){ + return pseudo.call(this, argument); + }; + return null; +}; + +// Slick overrides accessor + +Slick.override = function(regexp, fn){ + local.override(regexp, fn); + return this; +}; + +Slick.isXML = local.isXML; + +Slick.uidOf = function(node){ + return local.getUIDHTML(node); +}; + +if (!this.Slick) this.Slick = Slick; + +}).apply(/**/(typeof exports != 'undefined') ? exports : /**/this); + + +/* +--- + +name: Element + +description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements. + +license: MIT-style license. + +requires: [Window, Document, Array, String, Function, Number, Slick.Parser, Slick.Finder] + +provides: [Element, Elements, $, $$, Iframe, Selectors] + +... +*/ + +var Element = function(tag, props){ + var konstructor = Element.Constructors[tag]; + if (konstructor) return konstructor(props); + if (typeof tag != 'string') return document.id(tag).set(props); + + if (!props) props = {}; + + if (!(/^[\w-]+$/).test(tag)){ + var parsed = Slick.parse(tag).expressions[0][0]; + tag = (parsed.tag == '*') ? 'div' : parsed.tag; + if (parsed.id && props.id == null) props.id = parsed.id; + + var attributes = parsed.attributes; + if (attributes) for (var i = 0, l = attributes.length; i < l; i++){ + var attr = attributes[i]; + if (props[attr.key] != null) continue; + + if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value; + else if (!attr.value && !attr.operator) props[attr.key] = true; + } + + if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' '); + } + + return document.newElement(tag, props); +}; + +if (Browser.Element) Element.prototype = Browser.Element.prototype; + +new Type('Element', Element).mirror(function(name){ + if (Array.prototype[name]) return; + + var obj = {}; + obj[name] = function(){ + var results = [], args = arguments, elements = true; + for (var i = 0, l = this.length; i < l; i++){ + var element = this[i], result = results[i] = element[name].apply(element, args); + elements = (elements && typeOf(result) == 'element'); + } + return (elements) ? new Elements(results) : results; + }; + + Elements.implement(obj); +}); + +if (!Browser.Element){ + Element.parent = Object; + + Element.Prototype = {'$family': Function.from('element').hide()}; + + Element.mirror(function(name, method){ + Element.Prototype[name] = method; + }); +} + +Element.Constructors = {}; + + + +var IFrame = new Type('IFrame', function(){ + var params = Array.link(arguments, { + properties: Type.isObject, + iframe: function(obj){ + return (obj != null); + } + }); + + var props = params.properties || {}, iframe; + if (params.iframe) iframe = document.id(params.iframe); + var onload = props.onload || function(){}; + delete props.onload; + props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick(); + iframe = new Element(iframe || 'iframe', props); + + var onLoad = function(){ + onload.call(iframe.contentWindow); + }; + + if (window.frames[props.id]) onLoad(); + else iframe.addListener('load', onLoad); + return iframe; +}); + +var Elements = this.Elements = function(nodes){ + if (nodes && nodes.length){ + var uniques = {}, node; + for (var i = 0; node = nodes[i++];){ + var uid = Slick.uidOf(node); + if (!uniques[uid]){ + uniques[uid] = true; + this.push(node); + } + } + } +}; + +Elements.prototype = {length: 0}; +Elements.parent = Array; + +new Type('Elements', Elements).implement({ + + filter: function(filter, bind){ + if (!filter) return this; + return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){ + return item.match(filter); + } : filter, bind)); + }.protect(), + + push: function(){ + var length = this.length; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) this[length++] = item; + } + return (this.length = length); + }.protect(), + + unshift: function(){ + var items = []; + for (var i = 0, l = arguments.length; i < l; i++){ + var item = document.id(arguments[i]); + if (item) items.push(item); + } + return Array.prototype.unshift.apply(this, items); + }.protect(), + + concat: function(){ + var newElements = new Elements(this); + for (var i = 0, l = arguments.length; i < l; i++){ + var item = arguments[i]; + if (Type.isEnumerable(item)) newElements.append(item); + else newElements.push(item); + } + return newElements; + }.protect(), + + append: function(collection){ + for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]); + return this; + }.protect(), + + empty: function(){ + while (this.length) delete this[--this.length]; + return this; + }.protect() + +}); + + + +(function(){ + +// FF, IE +var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2}; + +splice.call(object, 1, 1); +if (object[1] == 1) Elements.implement('splice', function(){ + var length = this.length; + splice.apply(this, arguments); + while (length >= this.length) delete this[length--]; + return this; +}.protect()); + +Elements.implement(Array.prototype); + +Array.mirror(Elements); + +/**/ +var createElementAcceptsHTML; +try { + var x = document.createElement(''); + createElementAcceptsHTML = (x.name == 'x'); +} catch(e){} + +var escapeQuotes = function(html){ + return ('' + html).replace(/&/g, '&').replace(/"/g, '"'); +}; +/**/ + +Document.implement({ + + newElement: function(tag, props){ + if (props && props.checked != null) props.defaultChecked = props.checked; + /**/// Fix for readonly name and type properties in IE < 8 + if (createElementAcceptsHTML && props){ + tag = '<' + tag; + if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"'; + if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"'; + tag += '>'; + delete props.name; + delete props.type; + } + /**/ + return this.id(this.createElement(tag)).set(props); + } + +}); + +})(); + +Document.implement({ + + newTextNode: function(text){ + return this.createTextNode(text); + }, + + getDocument: function(){ + return this; + }, + + getWindow: function(){ + return this.window; + }, + + id: (function(){ + + var types = { + + string: function(id, nocash, doc){ + id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1')); + return (id) ? types.element(id, nocash) : null; + }, + + element: function(el, nocash){ + $uid(el); + if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){ + Object.append(el, Element.Prototype); + } + return el; + }, + + object: function(obj, nocash, doc){ + if (obj.toElement) return types.element(obj.toElement(doc), nocash); + return null; + } + + }; + + types.textnode = types.whitespace = types.window = types.document = function(zero){ + return zero; + }; + + return function(el, nocash, doc){ + if (el && el.$family && el.uid) return el; + var type = typeOf(el); + return (types[type]) ? types[type](el, nocash, doc || document) : null; + }; + + })() + +}); + +if (window.$ == null) Window.implement('$', function(el, nc){ + return document.id(el, nc, this.document); +}); + +Window.implement({ + + getDocument: function(){ + return this.document; + }, + + getWindow: function(){ + return this; + } + +}); + +[Document, Element].invoke('implement', { + + getElements: function(expression){ + return Slick.search(this, expression, new Elements); + }, + + getElement: function(expression){ + return document.id(Slick.find(this, expression)); + } + +}); + + + +if (window.$$ == null) Window.implement('$$', function(selector){ + if (arguments.length == 1){ + if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements); + else if (Type.isEnumerable(selector)) return new Elements(selector); + } + return new Elements(arguments); +}); + +(function(){ + +var collected = {}, storage = {}; +var formProps = {input: 'checked', option: 'selected', textarea: 'value'}; + +var get = function(uid){ + return (storage[uid] || (storage[uid] = {})); +}; + +var clean = function(item){ + var uid = item.uid; + if (item.removeEvents) item.removeEvents(); + if (item.clearAttributes) item.clearAttributes(); + if (uid != null){ + delete collected[uid]; + delete storage[uid]; + } + return item; +}; + +var camels = ['defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', + 'rowSpan', 'tabIndex', 'useMap' +]; +var bools = ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readOnly', 'multiple', 'selected', + 'noresize', 'defer', 'defaultChecked' +]; + var attributes = { + 'html': 'innerHTML', + 'class': 'className', + 'for': 'htmlFor', + 'text': (function(){ + var temp = document.createElement('div'); + return (temp.textContent == null) ? 'innerText' : 'textContent'; + })() +}; +var readOnly = ['type']; +var expandos = ['value', 'defaultValue']; +var uriAttrs = /^(?:href|src|usemap)$/i; + +bools = bools.associate(bools); +camels = camels.associate(camels.map(String.toLowerCase)); +readOnly = readOnly.associate(readOnly); + +Object.append(attributes, expandos.associate(expandos)); + +var inserters = { + + before: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element); + }, + + after: function(context, element){ + var parent = element.parentNode; + if (parent) parent.insertBefore(context, element.nextSibling); + }, + + bottom: function(context, element){ + element.appendChild(context); + }, + + top: function(context, element){ + element.insertBefore(context, element.firstChild); + } + +}; + +inserters.inside = inserters.bottom; + + + +var injectCombinator = function(expression, combinator){ + if (!expression) return combinator; + + expression = Object.clone(Slick.parse(expression)); + + var expressions = expression.expressions; + for (var i = expressions.length; i--;) + expressions[i][0].combinator = combinator; + + return expression; +}; + +Element.implement({ + + set: function(prop, value){ + var property = Element.Properties[prop]; + (property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value); + }.overloadSetter(), + + get: function(prop){ + var property = Element.Properties[prop]; + return (property && property.get) ? property.get.apply(this) : this.getProperty(prop); + }.overloadGetter(), + + erase: function(prop){ + var property = Element.Properties[prop]; + (property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop); + return this; + }, + + setProperty: function(attribute, value){ + attribute = camels[attribute] || attribute; + if (value == null) return this.removeProperty(attribute); + var key = attributes[attribute]; + (key) ? this[key] = value : + (bools[attribute]) ? this[attribute] = !!value : this.setAttribute(attribute, '' + value); + return this; + }, + + setProperties: function(attributes){ + for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]); + return this; + }, + + getProperty: function(attribute){ + attribute = camels[attribute] || attribute; + var key = attributes[attribute] || readOnly[attribute]; + return (key) ? this[key] : + (bools[attribute]) ? !!this[attribute] : + (uriAttrs.test(attribute) ? this.getAttribute(attribute, 2) : + (key = this.getAttributeNode(attribute)) ? key.nodeValue : null) || null; + }, + + getProperties: function(){ + var args = Array.from(arguments); + return args.map(this.getProperty, this).associate(args); + }, + + removeProperty: function(attribute){ + attribute = camels[attribute] || attribute; + var key = attributes[attribute]; + (key) ? this[key] = '' : + (bools[attribute]) ? this[attribute] = false : this.removeAttribute(attribute); + return this; + }, + + removeProperties: function(){ + Array.each(arguments, this.removeProperty, this); + return this; + }, + + hasClass: function(className){ + return this.className.clean().contains(className, ' '); + }, + + addClass: function(className){ + if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean(); + return this; + }, + + removeClass: function(className){ + this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1'); + return this; + }, + + toggleClass: function(className, force){ + if (force == null) force = !this.hasClass(className); + return (force) ? this.addClass(className) : this.removeClass(className); + }, + + adopt: function(){ + var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length; + if (length > 1) parent = fragment = document.createDocumentFragment(); + + for (var i = 0; i < length; i++){ + var element = document.id(elements[i], true); + if (element) parent.appendChild(element); + } + + if (fragment) this.appendChild(fragment); + + return this; + }, + + appendText: function(text, where){ + return this.grab(this.getDocument().newTextNode(text), where); + }, + + grab: function(el, where){ + inserters[where || 'bottom'](document.id(el, true), this); + return this; + }, + + inject: function(el, where){ + inserters[where || 'bottom'](this, document.id(el, true)); + return this; + }, + + replaces: function(el){ + el = document.id(el, true); + el.parentNode.replaceChild(this, el); + return this; + }, + + wraps: function(el, where){ + el = document.id(el, true); + return this.replaces(el).grab(el, where); + }, + + getPrevious: function(expression){ + return document.id(Slick.find(this, injectCombinator(expression, '!~'))); + }, + + getAllPrevious: function(expression){ + return Slick.search(this, injectCombinator(expression, '!~'), new Elements); + }, + + getNext: function(expression){ + return document.id(Slick.find(this, injectCombinator(expression, '~'))); + }, + + getAllNext: function(expression){ + return Slick.search(this, injectCombinator(expression, '~'), new Elements); + }, + + getFirst: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]); + }, + + getLast: function(expression){ + return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast()); + }, + + getParent: function(expression){ + return document.id(Slick.find(this, injectCombinator(expression, '!'))); + }, + + getParents: function(expression){ + return Slick.search(this, injectCombinator(expression, '!'), new Elements); + }, + + getSiblings: function(expression){ + return Slick.search(this, injectCombinator(expression, '~~'), new Elements); + }, + + getChildren: function(expression){ + return Slick.search(this, injectCombinator(expression, '>'), new Elements); + }, + + getWindow: function(){ + return this.ownerDocument.window; + }, + + getDocument: function(){ + return this.ownerDocument; + }, + + getElementById: function(id){ + return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1'))); + }, + + getSelected: function(){ + this.selectedIndex; // Safari 3.2.1 + return new Elements(Array.from(this.options).filter(function(option){ + return option.selected; + })); + }, + + toQueryString: function(){ + var queryString = []; + this.getElements('input, select, textarea').each(function(el){ + var type = el.type; + if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return; + + var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){ + // IE + return document.id(opt).get('value'); + }) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value'); + + Array.from(value).each(function(val){ + if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val)); + }); + }); + return queryString.join('&'); + }, + + destroy: function(){ + var children = clean(this).getElementsByTagName('*'); + Array.each(children, clean); + Element.dispose(this); + return null; + }, + + empty: function(){ + Array.from(this.childNodes).each(Element.dispose); + return this; + }, + + dispose: function(){ + return (this.parentNode) ? this.parentNode.removeChild(this) : this; + }, + + match: function(expression){ + return !expression || Slick.match(this, expression); + } + +}); + +var cleanClone = function(node, element, keepid){ + if (!keepid) node.setAttributeNode(document.createAttribute('id')); + if (node.clearAttributes){ + node.clearAttributes(); + node.mergeAttributes(element); + node.removeAttribute('uid'); + if (node.options){ + var no = node.options, eo = element.options; + for (var i = no.length; i--;) no[i].selected = eo[i].selected; + } + } + + var prop = formProps[element.tagName.toLowerCase()]; + if (prop && element[prop]) node[prop] = element[prop]; +}; + +Element.implement('clone', function(contents, keepid){ + contents = contents !== false; + var clone = this.cloneNode(contents), i; + + if (contents){ + var ce = clone.getElementsByTagName('*'), te = this.getElementsByTagName('*'); + for (i = ce.length; i--;) cleanClone(ce[i], te[i], keepid); + } + + cleanClone(clone, this, keepid); + + if (Browser.ie){ + var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object'); + for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML; + } + return document.id(clone); +}); + +var contains = {contains: function(element){ + return Slick.contains(this, element); +}}; + +if (!document.contains) Document.implement(contains); +if (!document.createElement('div').contains) Element.implement(contains); + + + +[Element, Window, Document].invoke('implement', { + + addListener: function(type, fn){ + if (type == 'unload'){ + var old = fn, self = this; + fn = function(){ + self.removeListener('unload', fn); + old(); + }; + } else { + collected[$uid(this)] = this; + } + if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]); + else this.attachEvent('on' + type, fn); + return this; + }, + + removeListener: function(type, fn){ + if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]); + else this.detachEvent('on' + type, fn); + return this; + }, + + retrieve: function(property, dflt){ + var storage = get($uid(this)), prop = storage[property]; + if (dflt != null && prop == null) prop = storage[property] = dflt; + return prop != null ? prop : null; + }, + + store: function(property, value){ + var storage = get($uid(this)); + storage[property] = value; + return this; + }, + + eliminate: function(property){ + var storage = get($uid(this)); + delete storage[property]; + return this; + } + +}); + +/**/ +if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){ + Object.each(collected, clean); + if (window.CollectGarbage) CollectGarbage(); +}); +/**/ + +})(); + +Element.Properties = {}; + + + +Element.Properties.style = { + + set: function(style){ + this.style.cssText = style; + }, + + get: function(){ + return this.style.cssText; + }, + + erase: function(){ + this.style.cssText = ''; + } + +}; + +Element.Properties.tag = { + + get: function(){ + return this.tagName.toLowerCase(); + } + +}; + +/**/ +(function(maxLength){ + if (maxLength != null) Element.Properties.maxlength = Element.Properties.maxLength = { + get: function(){ + var maxlength = this.getAttribute('maxLength'); + return maxlength == maxLength ? null : maxlength; + } + }; +})(document.createElement('input').getAttribute('maxLength')); +/**/ + +/**/ +Element.Properties.html = (function(){ + + var tableTest = Function.attempt(function(){ + var table = document.createElement('table'); + table.innerHTML = ''; + }); + + var wrapper = document.createElement('div'); + + var translations = { + table: [1, '', '
'], + select: [1, ''], + tbody: [2, '', '
'], + tr: [3, '', '
'] + }; + translations.thead = translations.tfoot = translations.tbody; + + var html = { + set: function(){ + var html = Array.flatten(arguments).join(''); + var wrap = (!tableTest && translations[this.get('tag')]); + if (wrap){ + var first = wrapper; + first.innerHTML = wrap[1] + html + wrap[2]; + for (var i = wrap[0]; i--;) first = first.firstChild; + this.empty().adopt(first.childNodes); + } else { + this.innerHTML = html; + } + } + }; + + html.erase = html.set; + + return html; +})(); +/**/ + + +/* +--- + +name: Element.Style + +description: Contains methods for interacting with the styles of Elements in a fashionable way. + +license: MIT-style license. + +requires: Element + +provides: Element.Style + +... +*/ + +(function(){ + +var html = document.html; + +Element.Properties.styles = {set: function(styles){ + this.setStyles(styles); +}}; + +var hasOpacity = (html.style.opacity != null); +var reAlpha = /alpha\(opacity=([\d.]+)\)/i; + +var setOpacity = function(element, opacity){ + if (!element.currentStyle || !element.currentStyle.hasLayout) element.style.zoom = 1; + if (hasOpacity){ + element.style.opacity = opacity; + } else { + opacity = (opacity * 100).limit(0, 100).round(); + opacity = (opacity == 100) ? '' : 'alpha(opacity=' + opacity + ')'; + var filter = element.style.filter || element.getComputedStyle('filter') || ''; + element.style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity; + } +}; + +Element.Properties.opacity = { + + set: function(opacity){ + var visibility = this.style.visibility; + if (opacity == 0 && visibility != 'hidden') this.style.visibility = 'hidden'; + else if (opacity != 0 && visibility != 'visible') this.style.visibility = 'visible'; + + setOpacity(this, opacity); + }, + + get: (hasOpacity) ? function(){ + var opacity = this.style.opacity || this.getComputedStyle('opacity'); + return (opacity == '') ? 1 : opacity; + } : function(){ + var opacity, filter = (this.style.filter || this.getComputedStyle('filter')); + if (filter) opacity = filter.match(reAlpha); + return (opacity == null || filter == null) ? 1 : (opacity[1] / 100); + } + +}; + +var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat'; + +Element.implement({ + + getComputedStyle: function(property){ + if (this.currentStyle) return this.currentStyle[property.camelCase()]; + var defaultView = Element.getDocument(this).defaultView, + computed = defaultView ? defaultView.getComputedStyle(this, null) : null; + return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null; + }, + + setOpacity: function(value){ + setOpacity(this, value); + return this; + }, + + getOpacity: function(){ + return this.get('opacity'); + }, + + setStyle: function(property, value){ + switch (property){ + case 'opacity': return this.set('opacity', parseFloat(value)); + case 'float': property = floatName; + } + property = property.camelCase(); + if (typeOf(value) != 'string'){ + var map = (Element.Styles[property] || '@').split(' '); + value = Array.from(value).map(function(val, i){ + if (!map[i]) return ''; + return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val; + }).join(' '); + } else if (value == String(Number(value))){ + value = Math.round(value); + } + this.style[property] = value; + return this; + }, + + getStyle: function(property){ + switch (property){ + case 'opacity': return this.get('opacity'); + case 'float': property = floatName; + } + property = property.camelCase(); + var result = this.style[property]; + if (!result || property == 'zIndex'){ + result = []; + for (var style in Element.ShortStyles){ + if (property != style) continue; + for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s)); + return result.join(' '); + } + result = this.getComputedStyle(property); + } + if (result){ + result = String(result); + var color = result.match(/rgba?\([\d\s,]+\)/); + if (color) result = result.replace(color[0], color[0].rgbToHex()); + } + if (Browser.opera || (Browser.ie && isNaN(parseFloat(result)))){ + if ((/^(height|width)$/).test(property)){ + var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0; + values.each(function(value){ + size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt(); + }, this); + return this['offset' + property.capitalize()] - size + 'px'; + } + if (Browser.opera && String(result).indexOf('px') != -1) return result; + if ((/^border(.+)Width|margin|padding/).test(property)) return '0px'; + } + return result; + }, + + setStyles: function(styles){ + for (var style in styles) this.setStyle(style, styles[style]); + return this; + }, + + getStyles: function(){ + var result = {}; + Array.flatten(arguments).each(function(key){ + result[key] = this.getStyle(key); + }, this); + return result; + } + +}); + +Element.Styles = { + left: '@px', top: '@px', bottom: '@px', right: '@px', + width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px', + backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)', + fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)', + margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)', + borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)', + zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@' +}; + + + +Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}}; + +['Top', 'Right', 'Bottom', 'Left'].each(function(direction){ + var Short = Element.ShortStyles; + var All = Element.Styles; + ['margin', 'padding'].each(function(style){ + var sd = style + direction; + Short[style][sd] = All[sd] = '@px'; + }); + var bd = 'border' + direction; + Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)'; + var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color'; + Short[bd] = {}; + Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px'; + Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@'; + Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)'; +}); + +})(); + + +/* +--- + +name: Element.Event + +description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events. + +license: MIT-style license. + +requires: [Element, Event] + +provides: Element.Event + +... +*/ + +(function(){ + +Element.Properties.events = {set: function(events){ + this.addEvents(events); +}}; + +[Element, Window, Document].invoke('implement', { + + addEvent: function(type, fn){ + var events = this.retrieve('events', {}); + if (!events[type]) events[type] = {keys: [], values: []}; + if (events[type].keys.contains(fn)) return this; + events[type].keys.push(fn); + var realType = type, + custom = Element.Events[type], + condition = fn, + self = this; + if (custom){ + if (custom.onAdd) custom.onAdd.call(this, fn); + if (custom.condition){ + condition = function(event){ + if (custom.condition.call(this, event)) return fn.call(this, event); + return true; + }; + } + realType = custom.base || realType; + } + var defn = function(){ + return fn.call(self); + }; + var nativeEvent = Element.NativeEvents[realType]; + if (nativeEvent){ + if (nativeEvent == 2){ + defn = function(event){ + event = new Event(event, self.getWindow()); + if (condition.call(self, event) === false) event.stop(); + }; + } + this.addListener(realType, defn, arguments[2]); + } + events[type].values.push(defn); + return this; + }, + + removeEvent: function(type, fn){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + var list = events[type]; + var index = list.keys.indexOf(fn); + if (index == -1) return this; + var value = list.values[index]; + delete list.keys[index]; + delete list.values[index]; + var custom = Element.Events[type]; + if (custom){ + if (custom.onRemove) custom.onRemove.call(this, fn); + type = custom.base || type; + } + return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this; + }, + + addEvents: function(events){ + for (var event in events) this.addEvent(event, events[event]); + return this; + }, + + removeEvents: function(events){ + var type; + if (typeOf(events) == 'object'){ + for (type in events) this.removeEvent(type, events[type]); + return this; + } + var attached = this.retrieve('events'); + if (!attached) return this; + if (!events){ + for (type in attached) this.removeEvents(type); + this.eliminate('events'); + } else if (attached[events]){ + attached[events].keys.each(function(fn){ + this.removeEvent(events, fn); + }, this); + delete attached[events]; + } + return this; + }, + + fireEvent: function(type, args, delay){ + var events = this.retrieve('events'); + if (!events || !events[type]) return this; + args = Array.from(args); + + events[type].keys.each(function(fn){ + if (delay) fn.delay(delay, this, args); + else fn.apply(this, args); + }, this); + return this; + }, + + cloneEvents: function(from, type){ + from = document.id(from); + var events = from.retrieve('events'); + if (!events) return this; + if (!type){ + for (var eventType in events) this.cloneEvents(from, eventType); + } else if (events[type]){ + events[type].keys.each(function(fn){ + this.addEvent(type, fn); + }, this); + } + return this; + } + +}); + +Element.NativeEvents = { + click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons + mousewheel: 2, DOMMouseScroll: 2, //mouse wheel + mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement + keydown: 2, keypress: 2, keyup: 2, //keyboard + orientationchange: 2, // mobile + touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch + gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture + focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements + load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window + error: 1, abort: 1, scroll: 1 //misc +}; + +var check = function(event){ + var related = event.relatedTarget; + if (related == null) return true; + if (!related) return false; + return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related)); +}; + +Element.Events = { + + mouseenter: { + base: 'mouseover', + condition: check + }, + + mouseleave: { + base: 'mouseout', + condition: check + }, + + mousewheel: { + base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel' + } + +}; + + + +})(); + + +/* +--- + +name: Element.Dimensions + +description: Contains methods to work with size, scroll, or positioning of Elements and the window object. + +license: MIT-style license. + +credits: + - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html). + - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html). + +requires: [Element, Element.Style] + +provides: [Element.Dimensions] + +... +*/ + +(function(){ + +var element = document.createElement('div'), + child = document.createElement('div'); +element.style.height = '0'; +element.appendChild(child); +var brokenOffsetParent = (child.offsetParent === element); +element = child = null; + +var isOffset = function(el){ + return styleString(el, 'position') != 'static' || isBody(el); +}; + +var isOffsetStatic = function(el){ + return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName); +}; + +Element.implement({ + + scrollTo: function(x, y){ + if (isBody(this)){ + this.getWindow().scrollTo(x, y); + } else { + this.scrollLeft = x; + this.scrollTop = y; + } + return this; + }, + + getSize: function(){ + if (isBody(this)) return this.getWindow().getSize(); + return {x: this.offsetWidth, y: this.offsetHeight}; + }, + + getScrollSize: function(){ + if (isBody(this)) return this.getWindow().getScrollSize(); + return {x: this.scrollWidth, y: this.scrollHeight}; + }, + + getScroll: function(){ + if (isBody(this)) return this.getWindow().getScroll(); + return {x: this.scrollLeft, y: this.scrollTop}; + }, + + getScrolls: function(){ + var element = this.parentNode, position = {x: 0, y: 0}; + while (element && !isBody(element)){ + position.x += element.scrollLeft; + position.y += element.scrollTop; + element = element.parentNode; + } + return position; + }, + + getOffsetParent: brokenOffsetParent ? function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset; + while ((element = element.parentNode)){ + if (isOffsetCheck(element)) return element; + } + return null; + } : function(){ + var element = this; + if (isBody(element) || styleString(element, 'position') == 'fixed') return null; + + try { + return element.offsetParent; + } catch(e) {} + return null; + }, + + getOffsets: function(){ + if (this.getBoundingClientRect && !Browser.Platform.ios){ + var bound = this.getBoundingClientRect(), + html = document.id(this.getDocument().documentElement), + htmlScroll = html.getScroll(), + elemScrolls = this.getScrolls(), + isFixed = (styleString(this, 'position') == 'fixed'); + + return { + x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft, + y: bound.top.toInt() + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop + }; + } + + var element = this, position = {x: 0, y: 0}; + if (isBody(this)) return position; + + while (element && !isBody(element)){ + position.x += element.offsetLeft; + position.y += element.offsetTop; + + if (Browser.firefox){ + if (!borderBox(element)){ + position.x += leftBorder(element); + position.y += topBorder(element); + } + var parent = element.parentNode; + if (parent && styleString(parent, 'overflow') != 'visible'){ + position.x += leftBorder(parent); + position.y += topBorder(parent); + } + } else if (element != this && Browser.safari){ + position.x += leftBorder(element); + position.y += topBorder(element); + } + + element = element.offsetParent; + } + if (Browser.firefox && !borderBox(this)){ + position.x -= leftBorder(this); + position.y -= topBorder(this); + } + return position; + }, + + getPosition: function(relative){ + if (isBody(this)) return {x: 0, y: 0}; + var offset = this.getOffsets(), + scroll = this.getScrolls(); + var position = { + x: offset.x - scroll.x, + y: offset.y - scroll.y + }; + + if (relative && (relative = document.id(relative))){ + var relativePosition = relative.getPosition(); + return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)}; + } + return position; + }, + + getCoordinates: function(element){ + if (isBody(this)) return this.getWindow().getCoordinates(); + var position = this.getPosition(element), + size = this.getSize(); + var obj = { + left: position.x, + top: position.y, + width: size.x, + height: size.y + }; + obj.right = obj.left + obj.width; + obj.bottom = obj.top + obj.height; + return obj; + }, + + computePosition: function(obj){ + return { + left: obj.x - styleNumber(this, 'margin-left'), + top: obj.y - styleNumber(this, 'margin-top') + }; + }, + + setPosition: function(obj){ + return this.setStyles(this.computePosition(obj)); + } + +}); + + +[Document, Window].invoke('implement', { + + getSize: function(){ + var doc = getCompatElement(this); + return {x: doc.clientWidth, y: doc.clientHeight}; + }, + + getScroll: function(){ + var win = this.getWindow(), doc = getCompatElement(this); + return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop}; + }, + + getScrollSize: function(){ + var doc = getCompatElement(this), + min = this.getSize(), + body = this.getDocument().body; + + return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)}; + }, + + getPosition: function(){ + return {x: 0, y: 0}; + }, + + getCoordinates: function(){ + var size = this.getSize(); + return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x}; + } + +}); + +// private methods + +var styleString = Element.getComputedStyle; + +function styleNumber(element, style){ + return styleString(element, style).toInt() || 0; +} + +function borderBox(element){ + return styleString(element, '-moz-box-sizing') == 'border-box'; +} + +function topBorder(element){ + return styleNumber(element, 'border-top-width'); +} + +function leftBorder(element){ + return styleNumber(element, 'border-left-width'); +} + +function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); +} + +function getCompatElement(element){ + var doc = element.getDocument(); + return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body; +} + +})(); + +//aliases +Element.alias({position: 'setPosition'}); //compatability + +[Window, Document, Element].invoke('implement', { + + getHeight: function(){ + return this.getSize().y; + }, + + getWidth: function(){ + return this.getSize().x; + }, + + getScrollTop: function(){ + return this.getScroll().y; + }, + + getScrollLeft: function(){ + return this.getScroll().x; + }, + + getScrollHeight: function(){ + return this.getScrollSize().y; + }, + + getScrollWidth: function(){ + return this.getScrollSize().x; + }, + + getTop: function(){ + return this.getPosition().y; + }, + + getLeft: function(){ + return this.getPosition().x; + } + +}); + + +/* +--- + +name: Fx + +description: Contains the basic animation logic to be extended by all other Fx Classes. + +license: MIT-style license. + +requires: [Chain, Events, Options] + +provides: Fx + +... +*/ + +(function(){ + +var Fx = this.Fx = new Class({ + + Implements: [Chain, Events, Options], + + options: { + /* + onStart: nil, + onCancel: nil, + onComplete: nil, + */ + fps: 60, + unit: false, + duration: 500, + frames: null, + frameSkip: true, + link: 'ignore' + }, + + initialize: function(options){ + this.subject = this.subject || this; + this.setOptions(options); + }, + + getTransition: function(){ + return function(p){ + return -(Math.cos(Math.PI * p) - 1) / 2; + }; + }, + + step: function(now){ + if (this.options.frameSkip){ + var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval; + this.time = now; + this.frame += frames; + } else { + this.frame++; + } + + if (this.frame < this.frames){ + var delta = this.transition(this.frame / this.frames); + this.set(this.compute(this.from, this.to, delta)); + } else { + this.frame = this.frames; + this.set(this.compute(this.from, this.to, 1)); + this.stop(); + } + }, + + set: function(now){ + return now; + }, + + compute: function(from, to, delta){ + return Fx.compute(from, to, delta); + }, + + check: function(){ + if (!this.isRunning()) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + start: function(from, to){ + if (!this.check(from, to)) return this; + this.from = from; + this.to = to; + this.frame = (this.options.frameSkip) ? 0 : -1; + this.time = null; + this.transition = this.getTransition(); + var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration; + this.duration = Fx.Durations[duration] || duration.toInt(); + this.frameInterval = 1000 / fps; + this.frames = frames || Math.round(this.duration / this.frameInterval); + this.fireEvent('start', this.subject); + pushInstance.call(this, fps); + return this; + }, + + stop: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + if (this.frames == this.frame){ + this.fireEvent('complete', this.subject); + if (!this.callChain()) this.fireEvent('chainComplete', this.subject); + } else { + this.fireEvent('stop', this.subject); + } + } + return this; + }, + + cancel: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + this.frame = this.frames; + this.fireEvent('cancel', this.subject).clearChain(); + } + return this; + }, + + pause: function(){ + if (this.isRunning()){ + this.time = null; + pullInstance.call(this, this.options.fps); + } + return this; + }, + + resume: function(){ + if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps); + return this; + }, + + isRunning: function(){ + var list = instances[this.options.fps]; + return list && list.contains(this); + } + +}); + +Fx.compute = function(from, to, delta){ + return (to - from) * delta + from; +}; + +Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000}; + +// global timers + +var instances = {}, timers = {}; + +var loop = function(){ + var now = Date.now(); + for (var i = this.length; i--;){ + var instance = this[i]; + if (instance) instance.step(now); + } +}; + +var pushInstance = function(fps){ + var list = instances[fps] || (instances[fps] = []); + list.push(this); + if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list); +}; + +var pullInstance = function(fps){ + var list = instances[fps]; + if (list){ + list.erase(this); + if (!list.length && timers[fps]){ + delete instances[fps]; + timers[fps] = clearInterval(timers[fps]); + } + } +}; + +})(); + + +/* +--- + +name: Fx.CSS + +description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. + +license: MIT-style license. + +requires: [Fx, Element.Style] + +provides: Fx.CSS + +... +*/ + +Fx.CSS = new Class({ + + Extends: Fx, + + //prepares the base from/to object + + prepare: function(element, property, values){ + values = Array.from(values); + if (values[1] == null){ + values[1] = values[0]; + values[0] = element.getStyle(property); + } + var parsed = values.map(this.parse); + return {from: parsed[0], to: parsed[1]}; + }, + + //parses a value into an array + + parse: function(value){ + value = Function.from(value)(); + value = (typeof value == 'string') ? value.split(' ') : Array.from(value); + return value.map(function(val){ + val = String(val); + var found = false; + Object.each(Fx.CSS.Parsers, function(parser, key){ + if (found) return; + var parsed = parser.parse(val); + if (parsed || parsed === 0) found = {value: parsed, parser: parser}; + }); + found = found || {value: val, parser: Fx.CSS.Parsers.String}; + return found; + }); + }, + + //computes by a from and to prepared objects, using their parsers. + + compute: function(from, to, delta){ + var computed = []; + (Math.min(from.length, to.length)).times(function(i){ + computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser}); + }); + computed.$family = Function.from('fx:css:value'); + return computed; + }, + + //serves the value as settable + + serve: function(value, unit){ + if (typeOf(value) != 'fx:css:value') value = this.parse(value); + var returned = []; + value.each(function(bit){ + returned = returned.concat(bit.parser.serve(bit.value, unit)); + }); + return returned; + }, + + //renders the change to an element + + render: function(element, property, value, unit){ + element.setStyle(property, this.serve(value, unit)); + }, + + //searches inside the page css to find the values for a selector + + search: function(selector){ + if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector]; + var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); + Array.each(document.styleSheets, function(sheet, j){ + var href = sheet.href; + if (href && href.contains('://') && !href.contains(document.domain)) return; + var rules = sheet.rules || sheet.cssRules; + Array.each(rules, function(rule, i){ + if (!rule.style) return; + var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){ + return m.toLowerCase(); + }) : null; + if (!selectorText || !selectorTest.test(selectorText)) return; + Object.each(Element.Styles, function(value, style){ + if (!rule.style[style] || Element.ShortStyles[style]) return; + value = String(rule.style[style]); + to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; + }); + }); + }); + return Fx.CSS.Cache[selector] = to; + } + +}); + +Fx.CSS.Cache = {}; + +Fx.CSS.Parsers = { + + Color: { + parse: function(value){ + if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true); + return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false; + }, + compute: function(from, to, delta){ + return from.map(function(value, i){ + return Math.round(Fx.compute(from[i], to[i], delta)); + }); + }, + serve: function(value){ + return value.map(Number); + } + }, + + Number: { + parse: parseFloat, + compute: Fx.compute, + serve: function(value, unit){ + return (unit) ? value + unit : value; + } + }, + + String: { + parse: Function.from(false), + compute: function(zero, one){ + return one; + }, + serve: function(zero){ + return zero; + } + } + +}; + + + + +/* +--- + +name: Fx.Tween + +description: Formerly Fx.Style, effect to transition any CSS property for an element. + +license: MIT-style license. + +requires: Fx.CSS + +provides: [Fx.Tween, Element.fade, Element.highlight] + +... +*/ + +Fx.Tween = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(property, now){ + if (arguments.length == 1){ + now = property; + property = this.property || this.options.property; + } + this.render(this.element, property, now, this.options.unit); + return this; + }, + + start: function(property, from, to){ + if (!this.check(property, from, to)) return this; + var args = Array.flatten(arguments); + this.property = this.options.property || args.shift(); + var parsed = this.prepare(this.element, this.property, args); + return this.parent(parsed.from, parsed.to); + } + +}); + +Element.Properties.tween = { + + set: function(options){ + this.get('tween').cancel().setOptions(options); + return this; + }, + + get: function(){ + var tween = this.retrieve('tween'); + if (!tween){ + tween = new Fx.Tween(this, {link: 'cancel'}); + this.store('tween', tween); + } + return tween; + } + +}; + +Element.implement({ + + tween: function(property, from, to){ + this.get('tween').start(arguments); + return this; + }, + + fade: function(how){ + var fade = this.get('tween'), o = 'opacity', toggle; + how = [how, 'toggle'].pick(); + switch (how){ + case 'in': fade.start(o, 1); break; + case 'out': fade.start(o, 0); break; + case 'show': fade.set(o, 1); break; + case 'hide': fade.set(o, 0); break; + case 'toggle': + var flag = this.retrieve('fade:flag', this.get('opacity') == 1); + fade.start(o, (flag) ? 0 : 1); + this.store('fade:flag', !flag); + toggle = true; + break; + default: fade.start(o, arguments); + } + if (!toggle) this.eliminate('fade:flag'); + return this; + }, + + highlight: function(start, end){ + if (!end){ + end = this.retrieve('highlight:original', this.getStyle('background-color')); + end = (end == 'transparent') ? '#fff' : end; + } + var tween = this.get('tween'); + tween.start('background-color', start || '#ffff88', end).chain(function(){ + this.setStyle('background-color', this.retrieve('highlight:original')); + tween.callChain(); + }.bind(this)); + return this; + } + +}); + + +/* +--- + +name: Fx.Morph + +description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules. + +license: MIT-style license. + +requires: Fx.CSS + +provides: Fx.Morph + +... +*/ + +Fx.Morph = new Class({ + + Extends: Fx.CSS, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + }, + + set: function(now){ + if (typeof now == 'string') now = this.search(now); + for (var p in now) this.render(this.element, p, now[p], this.options.unit); + return this; + }, + + compute: function(from, to, delta){ + var now = {}; + for (var p in from) now[p] = this.parent(from[p], to[p], delta); + return now; + }, + + start: function(properties){ + if (!this.check(properties)) return this; + if (typeof properties == 'string') properties = this.search(properties); + var from = {}, to = {}; + for (var p in properties){ + var parsed = this.prepare(this.element, p, properties[p]); + from[p] = parsed.from; + to[p] = parsed.to; + } + return this.parent(from, to); + } + +}); + +Element.Properties.morph = { + + set: function(options){ + this.get('morph').cancel().setOptions(options); + return this; + }, + + get: function(){ + var morph = this.retrieve('morph'); + if (!morph){ + morph = new Fx.Morph(this, {link: 'cancel'}); + this.store('morph', morph); + } + return morph; + } + +}; + +Element.implement({ + + morph: function(props){ + this.get('morph').start(props); + return this; + } + +}); + + +/* +--- + +name: Fx.Transitions + +description: Contains a set of advanced transitions to be used with any of the Fx Classes. + +license: MIT-style license. + +credits: + - Easing Equations by Robert Penner, , modified and optimized to be used with MooTools. + +requires: Fx + +provides: Fx.Transitions + +... +*/ + +Fx.implement({ + + getTransition: function(){ + var trans = this.options.transition || Fx.Transitions.Sine.easeInOut; + if (typeof trans == 'string'){ + var data = trans.split(':'); + trans = Fx.Transitions; + trans = trans[data[0]] || trans[data[0].capitalize()]; + if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')]; + } + return trans; + } + +}); + +Fx.Transition = function(transition, params){ + params = Array.from(params); + var easeIn = function(pos){ + return transition(pos, params); + }; + return Object.append(easeIn, { + easeIn: easeIn, + easeOut: function(pos){ + return 1 - transition(1 - pos, params); + }, + easeInOut: function(pos){ + return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2; + } + }); +}; + +Fx.Transitions = { + + linear: function(zero){ + return zero; + } + +}; + + + +Fx.Transitions.extend = function(transitions){ + for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]); +}; + +Fx.Transitions.extend({ + + Pow: function(p, x){ + return Math.pow(p, x && x[0] || 6); + }, + + Expo: function(p){ + return Math.pow(2, 8 * (p - 1)); + }, + + Circ: function(p){ + return 1 - Math.sin(Math.acos(p)); + }, + + Sine: function(p){ + return 1 - Math.cos(p * Math.PI / 2); + }, + + Back: function(p, x){ + x = x && x[0] || 1.618; + return Math.pow(p, 2) * ((x + 1) * p - x); + }, + + Bounce: function(p){ + var value; + for (var a = 0, b = 1; 1; a += b, b /= 2){ + if (p >= (7 - 4 * a) / 11){ + value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2); + break; + } + } + return value; + }, + + Elastic: function(p, x){ + return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3); + } + +}); + +['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){ + Fx.Transitions[transition] = new Fx.Transition(function(p){ + return Math.pow(p, i + 2); + }); +}); + + +/* +--- + +name: Request + +description: Powerful all purpose Request Class. Uses XMLHTTPRequest. + +license: MIT-style license. + +requires: [Object, Element, Chain, Events, Options, Browser] + +provides: Request + +... +*/ + +(function(){ + +var empty = function(){}, + progressSupport = ('onprogress' in new Browser.Request); + +var Request = this.Request = new Class({ + + Implements: [Chain, Events, Options], + + options: {/* + onRequest: function(){}, + onLoadstart: function(event, xhr){}, + onProgress: function(event, xhr){}, + onComplete: function(){}, + onCancel: function(){}, + onSuccess: function(responseText, responseXML){}, + onFailure: function(xhr){}, + onException: function(headerName, value){}, + onTimeout: function(){}, + user: '', + password: '',*/ + url: '', + data: '', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }, + async: true, + format: false, + method: 'post', + link: 'ignore', + isSuccess: null, + emulation: true, + urlEncoded: true, + encoding: 'utf-8', + evalScripts: false, + evalResponse: false, + timeout: 0, + noCache: false + }, + + initialize: function(options){ + this.xhr = new Browser.Request(); + this.setOptions(options); + this.headers = this.options.headers; + }, + + onStateChange: function(){ + var xhr = this.xhr; + if (xhr.readyState != 4 || !this.running) return; + this.running = false; + this.status = 0; + Function.attempt(function(){ + var status = xhr.status; + this.status = (status == 1223) ? 204 : status; + }.bind(this)); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + clearTimeout(this.timer); + + this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML}; + if (this.options.isSuccess.call(this, this.status)) + this.success(this.response.text, this.response.xml); + else + this.failure(); + }, + + isSuccess: function(){ + var status = this.status; + return (status >= 200 && status < 300); + }, + + isRunning: function(){ + return !!this.running; + }, + + processScripts: function(text){ + if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text); + return text.stripScripts(this.options.evalScripts); + }, + + success: function(text, xml){ + this.onSuccess(this.processScripts(text), xml); + }, + + onSuccess: function(){ + this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain(); + }, + + failure: function(){ + this.onFailure(); + }, + + onFailure: function(){ + this.fireEvent('complete').fireEvent('failure', this.xhr); + }, + + loadstart: function(event){ + this.fireEvent('loadstart', [event, this.xhr]); + }, + + progress: function(event){ + this.fireEvent('progress', [event, this.xhr]); + }, + + timeout: function(){ + this.fireEvent('timeout', this.xhr); + }, + + setHeader: function(name, value){ + this.headers[name] = value; + return this; + }, + + getHeader: function(name){ + return Function.attempt(function(){ + return this.xhr.getResponseHeader(name); + }.bind(this)); + }, + + check: function(){ + if (!this.running) return true; + switch (this.options.link){ + case 'cancel': this.cancel(); return true; + case 'chain': this.chain(this.caller.pass(arguments, this)); return false; + } + return false; + }, + + send: function(options){ + if (!this.check(options)) return this; + + this.options.isSuccess = this.options.isSuccess || this.isSuccess; + this.running = true; + + var type = typeOf(options); + if (type == 'string' || type == 'element') options = {data: options}; + + var old = this.options; + options = Object.append({data: old.data, url: old.url, method: old.method}, options); + var data = options.data, url = String(options.url), method = options.method.toLowerCase(); + + switch (typeOf(data)){ + case 'element': data = document.id(data).toQueryString(); break; + case 'object': case 'hash': data = Object.toQueryString(data); + } + + if (this.options.format){ + var format = 'format=' + this.options.format; + data = (data) ? format + '&' + data : format; + } + + if (this.options.emulation && !['get', 'post'].contains(method)){ + var _method = '_method=' + method; + data = (data) ? _method + '&' + data : _method; + method = 'post'; + } + + if (this.options.urlEncoded && ['post', 'put'].contains(method)){ + var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : ''; + this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding; + } + + if (!url) url = document.location.pathname; + + var trimPosition = url.lastIndexOf('/'); + if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition); + + if (this.options.noCache) + url += (url.contains('?') ? '&' : '?') + String.uniqueID(); + + if (data && method == 'get'){ + url += (url.contains('?') ? '&' : '?') + data; + data = null; + } + + var xhr = this.xhr; + if (progressSupport){ + xhr.onloadstart = this.loadstart.bind(this); + xhr.onprogress = this.progress.bind(this); + } + + xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password); + if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true; + + xhr.onreadystatechange = this.onStateChange.bind(this); + + Object.each(this.headers, function(value, key){ + try { + xhr.setRequestHeader(key, value); + } catch (e){ + this.fireEvent('exception', [key, value]); + } + }, this); + + this.fireEvent('request'); + xhr.send(data); + if (!this.options.async) this.onStateChange(); + if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this); + return this; + }, + + cancel: function(){ + if (!this.running) return this; + this.running = false; + var xhr = this.xhr; + xhr.abort(); + clearTimeout(this.timer); + xhr.onreadystatechange = empty; + if (progressSupport) xhr.onprogress = xhr.onloadstart = empty; + this.xhr = new Browser.Request(); + this.fireEvent('cancel'); + return this; + } + +}); + +var methods = {}; +['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){ + methods[method] = function(data){ + var object = { + method: method + }; + if (data != null) object.data = data; + return this.send(object); + }; +}); + +Request.implement(methods); + +Element.Properties.send = { + + set: function(options){ + var send = this.get('send').cancel(); + send.setOptions(options); + return this; + }, + + get: function(){ + var send = this.retrieve('send'); + if (!send){ + send = new Request({ + data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action') + }); + this.store('send', send); + } + return send; + } + +}; + +Element.implement({ + + send: function(url){ + var sender = this.get('send'); + sender.send({data: this, url: url || sender.options.url}); + return this; + } + +}); + +})(); + +/* +--- + +name: Request.HTML + +description: Extends the basic Request Class with additional methods for interacting with HTML responses. + +license: MIT-style license. + +requires: [Element, Request] + +provides: Request.HTML + +... +*/ + +Request.HTML = new Class({ + + Extends: Request, + + options: { + update: false, + append: false, + evalScripts: true, + filter: false, + headers: { + Accept: 'text/html, application/xml, text/xml, */*' + } + }, + + success: function(text){ + var options = this.options, response = this.response; + + response.html = text.stripScripts(function(script){ + response.javascript = script; + }); + + var match = response.html.match(/]*>([\s\S]*?)<\/body>/i); + if (match) response.html = match[1]; + var temp = new Element('div').set('html', response.html); + + response.tree = temp.childNodes; + response.elements = temp.getElements('*'); + + if (options.filter) response.tree = response.elements.filter(options.filter); + if (options.update) document.id(options.update).empty().set('html', response.html); + else if (options.append) document.id(options.append).adopt(temp.getChildren()); + if (options.evalScripts) Browser.exec(response.javascript); + + this.onSuccess(response.tree, response.elements, response.html, response.javascript); + } + +}); + +Element.Properties.load = { + + set: function(options){ + var load = this.get('load').cancel(); + load.setOptions(options); + return this; + }, + + get: function(){ + var load = this.retrieve('load'); + if (!load){ + load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'}); + this.store('load', load); + } + return load; + } + +}; + +Element.implement({ + + load: function(){ + this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString})); + return this; + } + +}); + + +/* +--- + +name: JSON + +description: JSON encoder and decoder. + +license: MIT-style license. + +See Also: + +requires: [Array, String, Number, Function] + +provides: JSON + +... +*/ + +if (typeof JSON == 'undefined') this.JSON = {}; + + + +(function(){ + +var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'}; + +var escape = function(chr){ + return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4); +}; + +JSON.validate = function(string){ + string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@'). + replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'). + replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + + return (/^[\],:{}\s]*$/).test(string); +}; + +JSON.encode = JSON.stringify ? function(obj){ + return JSON.stringify(obj); +} : function(obj){ + if (obj && obj.toJSON) obj = obj.toJSON(); + + switch (typeOf(obj)){ + case 'string': + return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"'; + case 'array': + return '[' + obj.map(JSON.encode).clean() + ']'; + case 'object': case 'hash': + var string = []; + Object.each(obj, function(value, key){ + var json = JSON.encode(value); + if (json) string.push(JSON.encode(key) + ':' + json); + }); + return '{' + string + '}'; + case 'number': case 'boolean': return '' + obj; + case 'null': return 'null'; + } + + return null; +}; + +JSON.decode = function(string, secure){ + if (!string || typeOf(string) != 'string') return null; + + if (secure || JSON.secure){ + if (JSON.parse) return JSON.parse(string); + if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.'); + } + + return eval('(' + string + ')'); +}; + +})(); + + +/* +--- + +name: Request.JSON + +description: Extends the basic Request Class with additional methods for sending and receiving JSON data. + +license: MIT-style license. + +requires: [Request, JSON] + +provides: Request.JSON + +... +*/ + +Request.JSON = new Class({ + + Extends: Request, + + options: { + /*onError: function(text, error){},*/ + secure: true + }, + + initialize: function(options){ + this.parent(options); + Object.append(this.headers, { + 'Accept': 'application/json', + 'X-Request': 'JSON' + }); + }, + + success: function(text){ + var json; + try { + json = this.response.json = JSON.decode(text, this.options.secure); + } catch (error){ + this.fireEvent('error', [text, error]); + return; + } + if (json == null) this.onFailure(); + else this.onSuccess(json, text); + } + +}); + + +/* +--- + +name: Cookie + +description: Class for creating, reading, and deleting browser Cookies. + +license: MIT-style license. + +credits: + - Based on the functions by Peter-Paul Koch (http://quirksmode.org). + +requires: [Options, Browser] + +provides: Cookie + +... +*/ + +var Cookie = new Class({ + + Implements: Options, + + options: { + path: '/', + domain: false, + duration: false, + secure: false, + document: document, + encode: true + }, + + initialize: function(key, options){ + this.key = key; + this.setOptions(options); + }, + + write: function(value){ + if (this.options.encode) value = encodeURIComponent(value); + if (this.options.domain) value += '; domain=' + this.options.domain; + if (this.options.path) value += '; path=' + this.options.path; + if (this.options.duration){ + var date = new Date(); + date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000); + value += '; expires=' + date.toGMTString(); + } + if (this.options.secure) value += '; secure'; + this.options.document.cookie = this.key + '=' + value; + return this; + }, + + read: function(){ + var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)'); + return (value) ? decodeURIComponent(value[1]) : null; + }, + + dispose: function(){ + new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write(''); + return this; + } + +}); + +Cookie.write = function(key, value, options){ + return new Cookie(key, options).write(value); +}; + +Cookie.read = function(key){ + return new Cookie(key).read(); +}; + +Cookie.dispose = function(key, options){ + return new Cookie(key, options).dispose(); +}; + + +/* +--- + +name: DOMReady + +description: Contains the custom event domready. + +license: MIT-style license. + +requires: [Browser, Element, Element.Event] + +provides: [DOMReady, DomReady] + +... +*/ + +(function(window, document){ + +var ready, + loaded, + checks = [], + shouldPoll, + timer, + testElement = document.createElement('div'); + +var domready = function(){ + clearTimeout(timer); + if (ready) return; + Browser.loaded = ready = true; + document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check); + + document.fireEvent('domready'); + window.fireEvent('domready'); +}; + +var check = function(){ + for (var i = checks.length; i--;) if (checks[i]()){ + domready(); + return true; + } + return false; +}; + +var poll = function(){ + clearTimeout(timer); + if (!check()) timer = setTimeout(poll, 10); +}; + +document.addListener('DOMContentLoaded', domready); + +/**/ +// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/ +// testElement.doScroll() throws when the DOM is not ready, only in the top window +var doScrollWorks = function(){ + try { + testElement.doScroll(); + return true; + } catch (e){} + return false; +} +// If doScroll works already, it can't be used to determine domready +// e.g. in an iframe +if (testElement.doScroll && !doScrollWorks()){ + checks.push(doScrollWorks); + shouldPoll = true; +} +/**/ + +if (document.readyState) checks.push(function(){ + var state = document.readyState; + return (state == 'loaded' || state == 'complete'); +}); + +if ('onreadystatechange' in document) document.addListener('readystatechange', check); +else shouldPoll = true; + +if (shouldPoll) poll(); + +Element.Events.domready = { + onAdd: function(fn){ + if (ready) fn.call(this); + } +}; + +// Make sure that domready fires before load +Element.Events.load = { + base: 'load', + onAdd: function(fn){ + if (loaded && this == window) fn.call(this); + }, + condition: function(){ + if (this == window){ + domready(); + delete Element.Events.load; + } + return true; + } +}; + +// This is based on the custom load event +window.addEvent('load', function(){ + loaded = true; +}); + +})(window, document); + + +/* +--- + +name: Swiff + +description: Wrapper for embedding SWF movies. Supports External Interface Communication. + +license: MIT-style license. + +credits: + - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject. + +requires: [Options, Object, Element] + +provides: Swiff + +... +*/ + +(function(){ + +var Swiff = this.Swiff = new Class({ + + Implements: Options, + + options: { + id: null, + height: 1, + width: 1, + container: null, + properties: {}, + params: { + quality: 'high', + allowScriptAccess: 'always', + wMode: 'window', + swLiveConnect: true + }, + callBacks: {}, + vars: {} + }, + + toElement: function(){ + return this.object; + }, + + initialize: function(path, options){ + this.instance = 'Swiff_' + String.uniqueID(); + + this.setOptions(options); + options = this.options; + var id = this.id = options.id || this.instance; + var container = document.id(options.container); + + Swiff.CallBacks[this.instance] = {}; + + var params = options.params, vars = options.vars, callBacks = options.callBacks; + var properties = Object.append({height: options.height, width: options.width}, options.properties); + + var self = this; + + for (var callBack in callBacks){ + Swiff.CallBacks[this.instance][callBack] = (function(option){ + return function(){ + return option.apply(self.object, arguments); + }; + })(callBacks[callBack]); + vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack; + } + + params.flashVars = Object.toQueryString(vars); + if (Browser.ie){ + properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'; + params.movie = path; + } else { + properties.type = 'application/x-shockwave-flash'; + } + properties.data = path; + + var build = ''; + } + build += ''; + this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild; + }, + + replaces: function(element){ + element = document.id(element, true); + element.parentNode.replaceChild(this.toElement(), element); + return this; + }, + + inject: function(element){ + document.id(element, true).appendChild(this.toElement()); + return this; + }, + + remote: function(){ + return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments)); + } + +}); + +Swiff.CallBacks = {}; + +Swiff.remote = function(obj, fn){ + var rs = obj.CallFunction('' + __flash__argumentsToXML(arguments, 2) + ''); + return eval(rs); +}; + +})(); + diff --git a/web/tools/mootools/mootools-core-1.3.2-yc.js b/web/tools/mootools/mootools-core-1.3.2-yc.js new file mode 100644 index 000000000..71a263b81 --- /dev/null +++ b/web/tools/mootools/mootools-core-1.3.2-yc.js @@ -0,0 +1,450 @@ +/* +--- +MooTools: the javascript framework + +web build: + - http://mootools.net/core/7c56cfef9dddcf170a5d68e3fb61cfd7 + +packager build: + - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff + +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ +(function(){this.MooTools={version:"1.3.2",build:"c9f1ff10e9e7facb65e9481049ed1b450959d587"};var o=this.typeOf=function(i){if(i==null){return"null";}if(i.$family){return i.$family(); +}if(i.nodeName){if(i.nodeType==1){return"element";}if(i.nodeType==3){return(/\S/).test(i.nodeValue)?"textnode":"whitespace";}}else{if(typeof i.length=="number"){if(i.callee){return"arguments"; +}if("item" in i){return"collection";}}}return typeof i;};var j=this.instanceOf=function(t,i){if(t==null){return false;}var s=t.$constructor||t.constructor; +while(s){if(s===i){return true;}s=s.parent;}return t instanceof i;};var f=this.Function;var p=true;for(var k in {toString:1}){p=null;}if(p){p=["hasOwnProperty","valueOf","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","constructor"]; +}f.prototype.overloadSetter=function(s){var i=this;return function(u,t){if(u==null){return this;}if(s||typeof u!="string"){for(var v in u){i.call(this,v,u[v]); +}if(p){for(var w=p.length;w--;){v=p[w];if(u.hasOwnProperty(v)){i.call(this,v,u[v]);}}}}else{i.call(this,u,t);}return this;};};f.prototype.overloadGetter=function(s){var i=this; +return function(u){var v,t;if(s||typeof u!="string"){v=u;}else{if(arguments.length>1){v=arguments;}}if(v){t={};for(var w=0;w-1:this.indexOf(a)>-1;},trim:function(){return this.replace(/^\s+|\s+$/g,"");},clean:function(){return this.replace(/\s+/g," ").trim(); +},camelCase:function(){return this.replace(/-\D/g,function(a){return a.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase()); +});},capitalize:function(){return this.replace(/\b[a-z]/g,function(a){return a.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1"); +},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(b){var a=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/); +return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=this.match(/\d{1,3}/g);return(a)?a.rgbToHex(b):null;},substitute:function(a,b){return this.replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1); +}return(a[c]!=null)?a[c]:"";});}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0).toFixed(a<0?-a:0); +return Math.round(this*a)/a;},times:function(b,c){for(var a=0;a1)?Array.slice(arguments,1):null;return function(){if(!b&&!arguments.length){return a.call(c);}if(b&&arguments.length){return a.apply(c,b.concat(Array.from(arguments))); +}return a.apply(c,b||arguments);};},pass:function(b,c){var a=this;if(b!=null){b=Array.from(b);}return function(){return a.apply(c,b||arguments);};},delay:function(b,c,a){return setTimeout(this.pass((a==null?[]:a),c),b); +},periodical:function(c,b,a){return setInterval(this.pass((a==null?[]:a),b),c);}});(function(){var a=Object.prototype.hasOwnProperty;Object.extend({subset:function(d,g){var f={}; +for(var e=0,b=g.length;e]*>([\s\S]*?)<\/script>/gi,function(r,s){e+=s+"\n"; +return"";});if(p===true){o.exec(e);}else{if(typeOf(p)=="function"){p(e,q);}}return q;});o.extend({Document:this.Document,Window:this.Window,Element:this.Element,Event:this.Event}); +this.Window=this.$constructor=new Type("Window",function(){});this.$family=Function.from("window").hide();Window.mirror(function(e,p){i[e]=p;});this.Document=k.$constructor=new Type("Document",function(){}); +k.$family=Function.from("document").hide();Document.mirror(function(e,p){k[e]=p;});k.html=k.documentElement;if(!k.head){k.head=k.getElementsByTagName("head")[0]; +}if(k.execCommand){try{k.execCommand("BackgroundImageCache",false,true);}catch(g){}}if(this.attachEvent&&!this.addEventListener){var d=function(){this.detachEvent("onunload",d); +k.head=k.html=k.window=null;};this.attachEvent("onunload",d);}var m=Array.from;try{m(k.html.childNodes);}catch(g){Array.from=function(p){if(typeof p!="string"&&Type.isEnumerable(p)&&typeOf(p)!="array"){var e=p.length,q=new Array(e); +while(e--){q[e]=p[e];}return q;}return m(p);};var l=Array.prototype,n=l.slice;["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice"].each(function(e){var p=l[e]; +Array[e]=function(q){return p.apply(Array.from(q),n.call(arguments,1));};});}})();var Event=new Type("Event",function(a,i){if(!i){i=window;}var o=i.document; +a=a||i.event;if(a.$extended){return a;}this.$extended=true;var n=a.type,k=a.target||a.srcElement,m={},c={},q=null,h,l,b,p;while(k&&k.nodeType==3){k=k.parentNode; +}if(n.indexOf("key")!=-1){b=a.which||a.keyCode;p=Object.keyOf(Event.Keys,b);if(n=="keydown"){var d=b-111;if(d>0&&d<13){p="f"+d;}}if(!p){p=String.fromCharCode(b).toLowerCase(); +}}else{if((/click|mouse|menu/i).test(n)){o=(!o.compatMode||o.compatMode=="CSS1Compat")?o.html:o.body;m={x:(a.pageX!=null)?a.pageX:a.clientX+o.scrollLeft,y:(a.pageY!=null)?a.pageY:a.clientY+o.scrollTop}; +c={x:(a.pageX!=null)?a.pageX-i.pageXOffset:a.clientX,y:(a.pageY!=null)?a.pageY-i.pageYOffset:a.clientY};if((/DOMMouseScroll|mousewheel/).test(n)){l=(a.wheelDelta)?a.wheelDelta/120:-(a.detail||0)/3; +}h=(a.which==3)||(a.button==2);if((/over|out/).test(n)){q=a.relatedTarget||a[(n=="mouseover"?"from":"to")+"Element"];var j=function(){while(q&&q.nodeType==3){q=q.parentNode; +}return true;};var g=(Browser.firefox2)?j.attempt():j();q=(g)?q:null;}}else{if((/gesture|touch/i).test(n)){this.rotation=a.rotation;this.scale=a.scale; +this.targetTouches=a.targetTouches;this.changedTouches=a.changedTouches;var f=this.touches=a.touches;if(f&&f[0]){var e=f[0];m={x:e.pageX,y:e.pageY};c={x:e.clientX,y:e.clientY}; +}}}}return Object.append(this,{event:a,type:n,page:m,client:c,rightClick:h,wheel:l,relatedTarget:document.id(q),target:document.id(k),code:b,key:p,shift:a.shiftKey,control:a.ctrlKey,alt:a.altKey,meta:a.metaKey}); +});Event.Keys={enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46};Event.implement({stop:function(){return this.stopPropagation().preventDefault(); +},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault(); +}else{this.event.returnValue=false;}return this;}});(function(){var a=this.Class=new Type("Class",function(h){if(instanceOf(h,Function)){h={initialize:h}; +}var g=function(){e(this);if(g.$prototyping){return this;}this.$caller=null;var i=(this.initialize)?this.initialize.apply(this,arguments):this;this.$caller=this.caller=null; +return i;}.extend(this).implement(h);g.$constructor=a;g.prototype.$constructor=g;g.prototype.parent=c;return g;});var c=function(){if(!this.$caller){throw new Error('The method "parent" cannot be called.'); +}var g=this.$caller.$name,h=this.$caller.$owner.parent,i=(h)?h.prototype[g]:null;if(!i){throw new Error('The method "'+g+'" has no parent.');}return i.apply(this,arguments); +};var e=function(g){for(var h in g){var j=g[h];switch(typeOf(j)){case"object":var i=function(){};i.prototype=j;g[h]=e(new i);break;case"array":g[h]=j.clone(); +break;}}return g;};var b=function(g,h,j){if(j.$origin){j=j.$origin;}var i=function(){if(j.$protected&&this.$caller==null){throw new Error('The method "'+h+'" cannot be called.'); +}var l=this.caller,m=this.$caller;this.caller=m;this.$caller=i;var k=j.apply(this,arguments);this.$caller=m;this.caller=l;return k;}.extend({$owner:g,$origin:j,$name:h}); +return i;};var f=function(h,i,g){if(a.Mutators.hasOwnProperty(h)){i=a.Mutators[h].call(this,i);if(i==null){return this;}}if(typeOf(i)=="function"){if(i.$hidden){return this; +}this.prototype[h]=(g)?i:b(this,h,i);}else{Object.merge(this.prototype,h,i);}return this;};var d=function(g){g.$prototyping=true;var h=new g;delete g.$prototyping; +return h;};a.implement("implement",f.overloadSetter());a.Mutators={Extends:function(g){this.parent=g;this.prototype=d(g);},Implements:function(g){Array.from(g).each(function(j){var h=new j; +for(var i in h){f.call(this,i,h[i],true);}},this);}};})();(function(){this.Chain=new Class({$chain:[],chain:function(){this.$chain.append(Array.flatten(arguments)); +return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;},clearChain:function(){this.$chain.empty(); +return this;}});var a=function(b){return b.replace(/^on([A-Z])/,function(c,d){return d.toLowerCase();});};this.Events=new Class({$events:{},addEvent:function(d,c,b){d=a(d); +this.$events[d]=(this.$events[d]||[]).include(c);if(b){c.internal=true;}return this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]);}return this; +},fireEvent:function(e,c,b){e=a(e);var d=this.$events[e];if(!d){return this;}c=Array.from(c);d.each(function(f){if(b){f.delay(b,this,c);}else{f.apply(this,c); +}},this);return this;},removeEvent:function(e,d){e=a(e);var c=this.$events[e];if(c&&!d.internal){var b=c.indexOf(d);if(b!=-1){delete c[b];}}return this; +},removeEvents:function(d){var e;if(typeOf(d)=="object"){for(e in d){this.removeEvent(e,d[e]);}return this;}if(d){d=a(d);}for(e in this.$events){if(d&&d!=e){continue; +}var c=this.$events[e];for(var b=c.length;b--;){if(b in c){this.removeEvent(e,c[b]);}}}return this;}});this.Options=new Class({setOptions:function(){var b=this.options=Object.merge.apply(null,[{},this.options].append(arguments)); +if(this.addEvent){for(var c in b){if(typeOf(b[c])!="function"||!(/^on[A-Z]/).test(c)){continue;}this.addEvent(c,b[c]);delete b[c];}}return this;}});})(); +(function(){var k,n,l,g,a={},c={},m=/\\/g;var e=function(q,p){if(q==null){return null;}if(q.Slick===true){return q;}q=(""+q).replace(/^\s+|\s+$/g,"");g=!!p; +var o=(g)?c:a;if(o[q]){return o[q];}k={Slick:true,expressions:[],raw:q,reverse:function(){return e(this.raw,true);}};n=-1;while(q!=(q=q.replace(j,b))){}k.length=k.expressions.length; +return o[k.raw]=(g)?h(k):k;};var i=function(o){if(o==="!"){return" ";}else{if(o===" "){return"!";}else{if((/^!/).test(o)){return o.replace(/^!/,"");}else{return"!"+o; +}}}};var h=function(u){var r=u.expressions;for(var p=0;p+)\\s*|(\\s+)|(+|\\*)|\\#(+)|\\.(+)|\\[\\s*(+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)".replace(//,"["+f(">+~`!@$%^&={}\\;/g,"(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])").replace(//g,"(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])")); +function b(x,s,D,z,r,C,q,B,A,y,u,F,G,v,p,w){if(s||n===-1){k.expressions[++n]=[];l=-1;if(s){return"";}}if(D||z||l===-1){D=D||" ";var t=k.expressions[n]; +if(g&&t[l]){t[l].reverseCombinator=i(D);}t[++l]={combinator:D,tag:"*"};}var o=k.expressions[n][l];if(r){o.tag=r.replace(m,"");}else{if(C){o.id=C.replace(m,""); +}else{if(q){q=q.replace(m,"");if(!o.classList){o.classList=[];}if(!o.classes){o.classes=[];}o.classList.push(q);o.classes.push({value:q,regexp:new RegExp("(^|\\s)"+f(q)+"(\\s|$)")}); +}else{if(G){w=w||p;w=w?w.replace(m,""):null;if(!o.pseudos){o.pseudos=[];}o.pseudos.push({key:G.replace(m,""),value:w,type:F.length==1?"class":"element"}); +}else{if(B){B=B.replace(m,"");u=(u||"").replace(m,"");var E,H;switch(A){case"^=":H=new RegExp("^"+f(u));break;case"$=":H=new RegExp(f(u)+"$");break;case"~=":H=new RegExp("(^|\\s)"+f(u)+"(\\s|$)"); +break;case"|=":H=new RegExp("^"+f(u)+"(-|$)");break;case"=":E=function(I){return u==I;};break;case"*=":E=function(I){return I&&I.indexOf(u)>-1;};break; +case"!=":E=function(I){return u!=I;};break;default:E=function(I){return !!I;};}if(u==""&&(/^[*$^]=$/).test(A)){E=function(){return false;};}if(!E){E=function(I){return I&&H.test(I); +};}if(!o.attributes){o.attributes=[];}o.attributes.push({key:B,operator:A,value:u,test:E});}}}}}return"";}var d=(this.Slick||{});d.parse=function(o){return e(o); +};d.escapeRegExp=f;if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this);(function(){var j={},l={},b=Object.prototype.toString; +j.isNativeCode=function(c){return(/\{\s*\[native code\]\s*\}/).test(""+c);};j.isXML=function(c){return(!!c.xmlVersion)||(!!c.xml)||(b.call(c)=="[object XMLDocument]")||(c.nodeType==9&&c.documentElement.nodeName!="HTML"); +};j.setDocument=function(w){var t=w.nodeType;if(t==9){}else{if(t){w=w.ownerDocument;}else{if(w.navigator){w=w.document;}else{return;}}}if(this.document===w){return; +}this.document=w;var y=w.documentElement,u=this.getUIDXML(y),o=l[u],A;if(o){for(A in o){this[A]=o[A];}return;}o=l[u]={};o.root=y;o.isXMLDocument=this.isXML(w); +o.brokenStarGEBTN=o.starSelectsClosedQSA=o.idGetsName=o.brokenMixedCaseQSA=o.brokenGEBCN=o.brokenCheckedQSA=o.brokenEmptyAttributeQSA=o.isHTMLDocument=o.nativeMatchesSelector=false; +var m,n,x,q,r;var s,c="slick_uniqueid";var z=w.createElement("div");var p=w.body||w.getElementsByTagName("body")[0]||y;p.appendChild(z);try{z.innerHTML=''; +o.isHTMLDocument=!!w.getElementById(c);}catch(v){}if(o.isHTMLDocument){z.style.display="none";z.appendChild(w.createComment(""));n=(z.getElementsByTagName("*").length>1); +try{z.innerHTML="foo";s=z.getElementsByTagName("*");m=(s&&!!s.length&&s[0].nodeName.charAt(0)=="/");}catch(v){}o.brokenStarGEBTN=n||m;try{z.innerHTML=''; +o.idGetsName=w.getElementById(c)===z.firstChild;}catch(v){}if(z.getElementsByClassName){try{z.innerHTML='';z.getElementsByClassName("b").length; +z.firstChild.className="b";q=(z.getElementsByClassName("b").length!=2);}catch(v){}try{z.innerHTML='';x=(z.getElementsByClassName("a").length!=2); +}catch(v){}o.brokenGEBCN=q||x;}if(z.querySelectorAll){try{z.innerHTML="foo";s=z.querySelectorAll("*");o.starSelectsClosedQSA=(s&&!!s.length&&s[0].nodeName.charAt(0)=="/"); +}catch(v){}try{z.innerHTML='';o.brokenMixedCaseQSA=!z.querySelectorAll(".MiX").length;}catch(v){}try{z.innerHTML=''; +o.brokenCheckedQSA=(z.querySelectorAll(":checked").length==0);}catch(v){}try{z.innerHTML='';o.brokenEmptyAttributeQSA=(z.querySelectorAll('[class*=""]').length!=0); +}catch(v){}}try{z.innerHTML='
';r=(z.firstChild.getAttribute("action")!="s");}catch(v){}o.nativeMatchesSelector=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector; +if(o.nativeMatchesSelector){try{o.nativeMatchesSelector.call(y,":slick");o.nativeMatchesSelector=null;}catch(v){}}}try{y.slick_expando=1;delete y.slick_expando; +o.getUID=this.getUIDHTML;}catch(v){o.getUID=this.getUIDXML;}p.removeChild(z);z=s=p=null;o.getAttribute=(o.isHTMLDocument&&r)?function(D,B){var E=this.attributeGetters[B]; +if(E){return E.call(D);}var C=D.getAttributeNode(B);return(C)?C.nodeValue:null;}:function(C,B){var D=this.attributeGetters[B];return(D)?D.call(C):C.getAttribute(B); +};o.hasAttribute=(y&&this.isNativeCode(y.hasAttribute))?function(C,B){return C.hasAttribute(B);}:function(C,B){C=C.getAttributeNode(B);return !!(C&&(C.specified||C.nodeValue)); +};o.contains=(y&&this.isNativeCode(y.contains))?function(B,C){return B.contains(C);}:(y&&y.compareDocumentPosition)?function(B,C){return B===C||!!(B.compareDocumentPosition(C)&16); +}:function(B,C){if(C){do{if(C===B){return true;}}while((C=C.parentNode));}return false;};o.documentSorter=(y.compareDocumentPosition)?function(C,B){if(!C.compareDocumentPosition||!B.compareDocumentPosition){return 0; +}return C.compareDocumentPosition(B)&4?-1:C===B?0:1;}:("sourceIndex" in y)?function(C,B){if(!C.sourceIndex||!B.sourceIndex){return 0;}return C.sourceIndex-B.sourceIndex; +}:(w.createRange)?function(E,C){if(!E.ownerDocument||!C.ownerDocument){return 0;}var D=E.ownerDocument.createRange(),B=C.ownerDocument.createRange();D.setStart(E,0); +D.setEnd(E,0);B.setStart(C,0);B.setEnd(C,0);return D.compareBoundaryPoints(Range.START_TO_END,B);}:null;y=null;for(A in o){this[A]=o[A];}};var e=/^([#.]?)((?:[\w-]+|\*))$/,g=/\[.+[*$^]=(?:""|'')?\]/,f={}; +j.search=function(U,z,H,s){var p=this.found=(s)?null:(H||[]);if(!U){return p;}else{if(U.navigator){U=U.document;}else{if(!U.nodeType){return p;}}}var F,O,V=this.uniques={},I=!!(H&&H.length),y=(U.nodeType==9); +if(this.document!==(y?U:U.ownerDocument)){this.setDocument(U);}if(I){for(O=p.length;O--;){V[this.getUID(p[O])]=true;}}if(typeof z=="string"){var r=z.match(e); +simpleSelectors:if(r){var u=r[1],v=r[2],A,E;if(!u){if(v=="*"&&this.brokenStarGEBTN){break simpleSelectors;}E=U.getElementsByTagName(v);if(s){return E[0]||null; +}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{if(u=="#"){if(!this.isHTMLDocument||!y){break simpleSelectors;}A=U.getElementById(v); +if(!A){return p;}if(this.idGetsName&&A.getAttributeNode("id").nodeValue!=v){break simpleSelectors;}if(s){return A||null;}if(!(I&&V[this.getUID(A)])){p.push(A); +}}else{if(u=="."){if(!this.isHTMLDocument||((!U.getElementsByClassName||this.brokenGEBCN)&&U.querySelectorAll)){break simpleSelectors;}if(U.getElementsByClassName&&!this.brokenGEBCN){E=U.getElementsByClassName(v); +if(s){return E[0]||null;}for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}else{var T=new RegExp("(^|\\s)"+d.escapeRegExp(v)+"(\\s|$)");E=U.getElementsByTagName("*"); +for(O=0;A=E[O++];){className=A.className;if(!(className&&T.test(className))){continue;}if(s){return A;}if(!(I&&V[this.getUID(A)])){p.push(A);}}}}}}if(I){this.sort(p); +}return(s)?null:p;}querySelector:if(U.querySelectorAll){if(!this.isHTMLDocument||f[z]||this.brokenMixedCaseQSA||(this.brokenCheckedQSA&&z.indexOf(":checked")>-1)||(this.brokenEmptyAttributeQSA&&g.test(z))||(!y&&z.indexOf(",")>-1)||d.disableQSA){break querySelector; +}var S=z,x=U;if(!y){var C=x.getAttribute("id"),t="slickid__";x.setAttribute("id",t);S="#"+t+" "+S;U=x.parentNode;}try{if(s){return U.querySelector(S)||null; +}else{E=U.querySelectorAll(S);}}catch(Q){f[z]=1;break querySelector;}finally{if(!y){if(C){x.setAttribute("id",C);}else{x.removeAttribute("id");}U=x;}}if(this.starSelectsClosedQSA){for(O=0; +A=E[O++];){if(A.nodeName>"@"&&!(I&&V[this.getUID(A)])){p.push(A);}}}else{for(O=0;A=E[O++];){if(!(I&&V[this.getUID(A)])){p.push(A);}}}if(I){this.sort(p); +}return p;}F=this.Slick.parse(z);if(!F.length){return p;}}else{if(z==null){return p;}else{if(z.Slick){F=z;}else{if(this.contains(U.documentElement||U,z)){(p)?p.push(z):p=z; +return p;}else{return p;}}}}this.posNTH={};this.posNTHLast={};this.posNTHType={};this.posNTHTypeLast={};this.push=(!I&&(s||(F.length==1&&F.expressions[0].length==1)))?this.pushArray:this.pushUID; +if(p==null){p=[];}var M,L,K;var B,J,D,c,q,G,W;var N,P,o,w,R=F.expressions;search:for(O=0;(P=R[O]);O++){for(M=0;(o=P[M]);M++){B="combinator:"+o.combinator; +if(!this[B]){continue search;}J=(this.isXMLDocument)?o.tag:o.tag.toUpperCase();D=o.id;c=o.classList;q=o.classes;G=o.attributes;W=o.pseudos;w=(M===(P.length-1)); +this.bitUniques={};if(w){this.uniques=V;this.found=p;}else{this.uniques={};this.found=[];}if(M===0){this[B](U,J,D,q,G,W,c);if(s&&w&&p.length){break search; +}}else{if(s&&w){for(L=0,K=N.length;L1)){this.sort(p);}return(s)?(p[0]||null):p;};j.uidx=1;j.uidk="slick-uniqueid";j.getUIDXML=function(m){var c=m.getAttribute(this.uidk); +if(!c){c=this.uidx++;m.setAttribute(this.uidk,c);}return c;};j.getUIDHTML=function(c){return c.uniqueNumber||(c.uniqueNumber=this.uidx++);};j.sort=function(c){if(!this.documentSorter){return c; +}c.sort(this.documentSorter);return c;};j.cacheNTH={};j.matchNTH=/^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;j.parseNTHArgument=function(p){var n=p.match(this.matchNTH); +if(!n){return false;}var o=n[2]||false;var m=n[1]||1;if(m=="-"){m=-1;}var c=+n[3]||0;n=(o=="n")?{a:m,b:c}:(o=="odd")?{a:2,b:1}:(o=="even")?{a:2,b:0}:{a:0,b:m}; +return(this.cacheNTH[p]=n);};j.createNTHPseudo=function(o,m,c,n){return function(r,p){var t=this.getUID(r);if(!this[c][t]){var z=r.parentNode;if(!z){return false; +}var q=z[o],s=1;if(n){var y=r.nodeName;do{if(q.nodeName!=y){continue;}this[c][this.getUID(q)]=s++;}while((q=q[m]));}else{do{if(q.nodeType!=1){continue; +}this[c][this.getUID(q)]=s++;}while((q=q[m]));}}p=p||"n";var u=this.cacheNTH[p]||this.parseNTHArgument(p);if(!u){return false;}var x=u.a,w=u.b,v=this[c][t]; +if(x==0){return w==v;}if(x>0){if(v":function(o,c,q,n,m,p){if((o=o.firstChild)){do{if(o.nodeType==1){this.push(o,c,q,n,m,p); +}}while((o=o.nextSibling));}},"+":function(o,c,q,n,m,p){while((o=o.nextSibling)){if(o.nodeType==1){this.push(o,c,q,n,m,p);break;}}},"^":function(o,c,q,n,m,p){o=o.firstChild; +if(o){if(o.nodeType==1){this.push(o,c,q,n,m,p);}else{this["combinator:+"](o,c,q,n,m,p);}}},"~":function(p,c,r,o,m,q){while((p=p.nextSibling)){if(p.nodeType!=1){continue; +}var n=this.getUID(p);if(this.bitUniques[n]){break;}this.bitUniques[n]=true;this.push(p,c,r,o,m,q);}},"++":function(o,c,q,n,m,p){this["combinator:+"](o,c,q,n,m,p); +this["combinator:!+"](o,c,q,n,m,p);},"~~":function(o,c,q,n,m,p){this["combinator:~"](o,c,q,n,m,p);this["combinator:!~"](o,c,q,n,m,p);},"!":function(o,c,q,n,m,p){while((o=o.parentNode)){if(o!==this.document){this.push(o,c,q,n,m,p); +}}},"!>":function(o,c,q,n,m,p){o=o.parentNode;if(o!==this.document){this.push(o,c,q,n,m,p);}},"!+":function(o,c,q,n,m,p){while((o=o.previousSibling)){if(o.nodeType==1){this.push(o,c,q,n,m,p); +break;}}},"!^":function(o,c,q,n,m,p){o=o.lastChild;if(o){if(o.nodeType==1){this.push(o,c,q,n,m,p);}else{this["combinator:!+"](o,c,q,n,m,p);}}},"!~":function(p,c,r,o,m,q){while((p=p.previousSibling)){if(p.nodeType!=1){continue; +}var n=this.getUID(p);if(this.bitUniques[n]){break;}this.bitUniques[n]=true;this.push(p,c,r,o,m,q);}}};for(var h in i){j["combinator:"+h]=i[h];}var k={empty:function(c){var m=c.firstChild; +return !(m&&m.nodeType==1)&&!(c.innerText||c.textContent||"").length;},not:function(c,m){return !this.matchNode(c,m);},contains:function(c,m){return(c.innerText||c.textContent||"").indexOf(m)>-1; +},"first-child":function(c){while((c=c.previousSibling)){if(c.nodeType==1){return false;}}return true;},"last-child":function(c){while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"only-child":function(n){var m=n;while((m=m.previousSibling)){if(m.nodeType==1){return false;}}var c=n;while((c=c.nextSibling)){if(c.nodeType==1){return false; +}}return true;},"nth-child":j.createNTHPseudo("firstChild","nextSibling","posNTH"),"nth-last-child":j.createNTHPseudo("lastChild","previousSibling","posNTHLast"),"nth-of-type":j.createNTHPseudo("firstChild","nextSibling","posNTHType",true),"nth-last-of-type":j.createNTHPseudo("lastChild","previousSibling","posNTHTypeLast",true),index:function(m,c){return this["pseudo:nth-child"](m,""+c+1); +},even:function(c){return this["pseudo:nth-child"](c,"2n");},odd:function(c){return this["pseudo:nth-child"](c,"2n+1");},"first-of-type":function(c){var m=c.nodeName; +while((c=c.previousSibling)){if(c.nodeName==m){return false;}}return true;},"last-of-type":function(c){var m=c.nodeName;while((c=c.nextSibling)){if(c.nodeName==m){return false; +}}return true;},"only-of-type":function(n){var m=n,o=n.nodeName;while((m=m.previousSibling)){if(m.nodeName==o){return false;}}var c=n;while((c=c.nextSibling)){if(c.nodeName==o){return false; +}}return true;},enabled:function(c){return !c.disabled;},disabled:function(c){return c.disabled;},checked:function(c){return c.checked||c.selected;},focus:function(c){return this.isHTMLDocument&&this.document.activeElement===c&&(c.href||c.type||this.hasAttribute(c,"tabindex")); +},root:function(c){return(c===this.root);},selected:function(c){return c.selected;}};for(var a in k){j["pseudo:"+a]=k[a];}j.attributeGetters={"class":function(){return this.getAttribute("class")||this.className; +},"for":function(){return("htmlFor" in this)?this.htmlFor:this.getAttribute("for");},href:function(){return("href" in this)?this.getAttribute("href",2):this.getAttribute("href"); +},style:function(){return(this.style)?this.style.cssText:this.getAttribute("style");},tabindex:function(){var c=this.getAttributeNode("tabindex");return(c&&c.specified)?c.nodeValue:null; +},type:function(){return this.getAttribute("type");}};var d=j.Slick=(this.Slick||{});d.version="1.1.5";d.search=function(m,n,c){return j.search(m,n,c); +};d.find=function(c,m){return j.search(c,m,null,true);};d.contains=function(c,m){j.setDocument(c);return j.contains(c,m);};d.getAttribute=function(m,c){return j.getAttribute(m,c); +};d.match=function(m,c){if(!(m&&c)){return false;}if(!c||c===m){return true;}j.setDocument(m);return j.matchNode(m,c);};d.defineAttributeGetter=function(c,m){j.attributeGetters[c]=m; +return this;};d.lookupAttributeGetter=function(c){return j.attributeGetters[c];};d.definePseudo=function(c,m){j["pseudo:"+c]=function(o,n){return m.call(o,n); +};return this;};d.lookupPseudo=function(c){var m=j["pseudo:"+c];if(m){return function(n){return m.call(this,n);};}return null;};d.override=function(m,c){j.override(m,c); +return this;};d.isXML=j.isXML;d.uidOf=function(c){return j.getUIDHTML(c);};if(!this.Slick){this.Slick=d;}}).apply((typeof exports!="undefined")?exports:this); +var Element=function(b,g){var h=Element.Constructors[b];if(h){return h(g);}if(typeof b!="string"){return document.id(b).set(g);}if(!g){g={};}if(!(/^[\w-]+$/).test(b)){var e=Slick.parse(b).expressions[0][0]; +b=(e.tag=="*")?"div":e.tag;if(e.id&&g.id==null){g.id=e.id;}var d=e.attributes;if(d){for(var f=0,c=d.length;f=this.length){delete this[e--];}return this; +}.protect());}Elements.implement(Array.prototype);Array.mirror(Elements);var f;try{var a=document.createElement("");f=(a.name=="x");}catch(c){}var d=function(e){return(""+e).replace(/&/g,"&").replace(/"/g,"""); +};Document.implement({newElement:function(e,h){if(h&&h.checked!=null){h.defaultChecked=h.checked;}if(f&&h){e="<"+e;if(h.name){e+=' name="'+d(h.name)+'"'; +}if(h.type){e+=' type="'+d(h.type)+'"';}e+=">";delete h.name;delete h.type;}return this.id(this.createElement(e)).set(h);}});})();Document.implement({newTextNode:function(a){return this.createTextNode(a); +},getDocument:function(){return this;},getWindow:function(){return this.window;},id:(function(){var a={string:function(d,c,b){d=Slick.find(b,"#"+d.replace(/(\W)/g,"\\$1")); +return(d)?a.element(d,c):null;},element:function(b,c){$uid(b);if(!c&&!b.$family&&!(/^(?:object|embed)$/i).test(b.tagName)){Object.append(b,Element.Prototype); +}return b;},object:function(c,d,b){if(c.toElement){return a.element(c.toElement(b),d);}return null;}};a.textnode=a.whitespace=a.window=a.document=function(b){return b; +};return function(c,e,d){if(c&&c.$family&&c.uid){return c;}var b=typeOf(c);return(a[b])?a[b](c,e,d||document):null;};})()});if(window.$==null){Window.implement("$",function(a,b){return document.id(a,b,this.document); +});}Window.implement({getDocument:function(){return this.document;},getWindow:function(){return this;}});[Document,Element].invoke("implement",{getElements:function(a){return Slick.search(this,a,new Elements); +},getElement:function(a){return document.id(Slick.find(this,a));}});if(window.$$==null){Window.implement("$$",function(a){if(arguments.length==1){if(typeof a=="string"){return Slick.search(this.document,a,new Elements); +}else{if(Type.isEnumerable(a)){return new Elements(a);}}}return new Elements(arguments);});}(function(){var k={},i={};var n={input:"checked",option:"selected",textarea:"value"}; +var e=function(p){return(i[p]||(i[p]={}));};var j=function(q){var p=q.uid;if(q.removeEvents){q.removeEvents();}if(q.clearAttributes){q.clearAttributes(); +}if(p!=null){delete k[p];delete i[p];}return q;};var o=["defaultValue","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"]; +var d=["compact","nowrap","ismap","declare","noshade","checked","disabled","readOnly","multiple","selected","noresize","defer","defaultChecked"];var g={html:"innerHTML","class":"className","for":"htmlFor",text:(function(){var p=document.createElement("div"); +return(p.textContent==null)?"innerText":"textContent";})()};var m=["type"];var h=["value","defaultValue"];var l=/^(?:href|src|usemap)$/i;d=d.associate(d); +o=o.associate(o.map(String.toLowerCase));m=m.associate(m);Object.append(g,h.associate(h));var c={before:function(q,p){var r=p.parentNode;if(r){r.insertBefore(q,p); +}},after:function(q,p){var r=p.parentNode;if(r){r.insertBefore(q,p.nextSibling);}},bottom:function(q,p){p.appendChild(q);},top:function(q,p){p.insertBefore(q,p.firstChild); +}};c.inside=c.bottom;var b=function(s,r){if(!s){return r;}s=Object.clone(Slick.parse(s));var q=s.expressions;for(var p=q.length;p--;){q[p][0].combinator=r; +}return s;};Element.implement({set:function(r,q){var p=Element.Properties[r];(p&&p.set)?p.set.call(this,q):this.setProperty(r,q);}.overloadSetter(),get:function(q){var p=Element.Properties[q]; +return(p&&p.get)?p.get.apply(this):this.getProperty(q);}.overloadGetter(),erase:function(q){var p=Element.Properties[q];(p&&p.erase)?p.erase.apply(this):this.removeProperty(q); +return this;},setProperty:function(q,r){q=o[q]||q;if(r==null){return this.removeProperty(q);}var p=g[q];(p)?this[p]=r:(d[q])?this[q]=!!r:this.setAttribute(q,""+r); +return this;},setProperties:function(p){for(var q in p){this.setProperty(q,p[q]);}return this;},getProperty:function(q){q=o[q]||q;var p=g[q]||m[q];return(p)?this[p]:(d[q])?!!this[q]:(l.test(q)?this.getAttribute(q,2):(p=this.getAttributeNode(q))?p.nodeValue:null)||null; +},getProperties:function(){var p=Array.from(arguments);return p.map(this.getProperty,this).associate(p);},removeProperty:function(q){q=o[q]||q;var p=g[q]; +(p)?this[p]="":(d[q])?this[q]=false:this.removeAttribute(q);return this;},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this; +},hasClass:function(p){return this.className.clean().contains(p," ");},addClass:function(p){if(!this.hasClass(p)){this.className=(this.className+" "+p).clean(); +}return this;},removeClass:function(p){this.className=this.className.replace(new RegExp("(^|\\s)"+p+"(?:\\s|$)"),"$1");return this;},toggleClass:function(p,q){if(q==null){q=!this.hasClass(p); +}return(q)?this.addClass(p):this.removeClass(p);},adopt:function(){var s=this,p,u=Array.flatten(arguments),t=u.length;if(t>1){s=p=document.createDocumentFragment(); +}for(var r=0;r"))[0]);},getLast:function(p){return document.id(Slick.search(this,b(p,">")).getLast()); +},getParent:function(p){return document.id(Slick.find(this,b(p,"!")));},getParents:function(p){return Slick.search(this,b(p,"!"),new Elements);},getSiblings:function(p){return Slick.search(this,b(p,"~~"),new Elements); +},getChildren:function(p){return Slick.search(this,b(p,">"),new Elements);},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument; +},getElementById:function(p){return document.id(Slick.find(this,"#"+(""+p).replace(/(\W)/g,"\\$1")));},getSelected:function(){this.selectedIndex;return new Elements(Array.from(this.options).filter(function(p){return p.selected; +}));},toQueryString:function(){var p=[];this.getElements("input, select, textarea").each(function(r){var q=r.type;if(!r.name||r.disabled||q=="submit"||q=="reset"||q=="file"||q=="image"){return; +}var s=(r.get("tag")=="select")?r.getSelected().map(function(t){return document.id(t).get("value");}):((q=="radio"||q=="checkbox")&&!r.checked)?null:r.get("value"); +Array.from(s).each(function(t){if(typeof t!="undefined"){p.push(encodeURIComponent(r.name)+"="+encodeURIComponent(t));}});});return p.join("&");},destroy:function(){var p=j(this).getElementsByTagName("*"); +Array.each(p,j);Element.dispose(this);return null;},empty:function(){Array.from(this.childNodes).each(Element.dispose);return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this; +},match:function(p){return !p||Slick.match(this,p);}});var a=function(t,s,q){if(!q){t.setAttributeNode(document.createAttribute("id"));}if(t.clearAttributes){t.clearAttributes(); +t.mergeAttributes(s);t.removeAttribute("uid");if(t.options){var u=t.options,p=s.options;for(var r=u.length;r--;){u[r].selected=p[r].selected;}}}var v=n[s.tagName.toLowerCase()]; +if(v&&s[v]){t[v]=s[v];}};Element.implement("clone",function(r,p){r=r!==false;var w=this.cloneNode(r),q;if(r){var s=w.getElementsByTagName("*"),u=this.getElementsByTagName("*"); +for(q=s.length;q--;){a(s[q],u[q],p);}}a(w,this,p);if(Browser.ie){var t=w.getElementsByTagName("object"),v=this.getElementsByTagName("object");for(q=t.length; +q--;){t[q].outerHTML=v[q].outerHTML;}}return document.id(w);});var f={contains:function(p){return Slick.contains(this,p);}};if(!document.contains){Document.implement(f); +}if(!document.createElement("div").contains){Element.implement(f);}[Element,Window,Document].invoke("implement",{addListener:function(s,r){if(s=="unload"){var p=r,q=this; +r=function(){q.removeListener("unload",r);p();};}else{k[$uid(this)]=this;}if(this.addEventListener){this.addEventListener(s,r,!!arguments[2]);}else{this.attachEvent("on"+s,r); +}return this;},removeListener:function(q,p){if(this.removeEventListener){this.removeEventListener(q,p,!!arguments[2]);}else{this.detachEvent("on"+q,p); +}return this;},retrieve:function(q,p){var s=e($uid(this)),r=s[q];if(p!=null&&r==null){r=s[q]=p;}return r!=null?r:null;},store:function(q,p){var r=e($uid(this)); +r[q]=p;return this;},eliminate:function(p){var q=e($uid(this));delete q[p];return this;}});if(window.attachEvent&&!window.addEventListener){window.addListener("unload",function(){Object.each(k,j); +if(window.CollectGarbage){CollectGarbage();}});}})();Element.Properties={};Element.Properties.style={set:function(a){this.style.cssText=a;},get:function(){return this.style.cssText; +},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();}};(function(a){if(a!=null){Element.Properties.maxlength=Element.Properties.maxLength={get:function(){var b=this.getAttribute("maxLength"); +return b==a?null:b;}};}})(document.createElement("input").getAttribute("maxLength"));Element.Properties.html=(function(){var c=Function.attempt(function(){var e=document.createElement("table"); +e.innerHTML="";});var d=document.createElement("div");var a={table:[1,"","
"],select:[1,""],tbody:[2,"","
"],tr:[3,"","
"]}; +a.thead=a.tfoot=a.tbody;var b={set:function(){var f=Array.flatten(arguments).join("");var g=(!c&&a[this.get("tag")]);if(g){var h=d;h.innerHTML=g[1]+f+g[2]; +for(var e=g[0];e--;){h=h.firstChild;}this.empty().adopt(h.childNodes);}else{this.innerHTML=f;}}};b.erase=b.set;return b;})();(function(){var c=document.html; +Element.Properties.styles={set:function(f){this.setStyles(f);}};var e=(c.style.opacity!=null);var d=/alpha\(opacity=([\d.]+)\)/i;var b=function(g,f){if(!g.currentStyle||!g.currentStyle.hasLayout){g.style.zoom=1; +}if(e){g.style.opacity=f;}else{f=(f*100).limit(0,100).round();f=(f==100)?"":"alpha(opacity="+f+")";var h=g.style.filter||g.getComputedStyle("filter")||""; +g.style.filter=d.test(h)?h.replace(d,f):h+f;}};Element.Properties.opacity={set:function(g){var f=this.style.visibility;if(g==0&&f!="hidden"){this.style.visibility="hidden"; +}else{if(g!=0&&f!="visible"){this.style.visibility="visible";}}b(this,g);},get:(e)?function(){var f=this.style.opacity||this.getComputedStyle("opacity"); +return(f=="")?1:f;}:function(){var f,g=(this.style.filter||this.getComputedStyle("filter"));if(g){f=g.match(d);}return(f==null||g==null)?1:(f[1]/100);}}; +var a=(c.style.cssFloat==null)?"styleFloat":"cssFloat";Element.implement({getComputedStyle:function(h){if(this.currentStyle){return this.currentStyle[h.camelCase()]; +}var g=Element.getDocument(this).defaultView,f=g?g.getComputedStyle(this,null):null;return(f)?f.getPropertyValue((h==a)?"float":h.hyphenate()):null;},setOpacity:function(f){b(this,f); +return this;},getOpacity:function(){return this.get("opacity");},setStyle:function(g,f){switch(g){case"opacity":return this.set("opacity",parseFloat(f)); +case"float":g=a;}g=g.camelCase();if(typeOf(f)!="string"){var h=(Element.Styles[g]||"@").split(" ");f=Array.from(f).map(function(k,j){if(!h[j]){return""; +}return(typeOf(k)=="number")?h[j].replace("@",Math.round(k)):k;}).join(" ");}else{if(f==String(Number(f))){f=Math.round(f);}}this.style[g]=f;return this; +},getStyle:function(l){switch(l){case"opacity":return this.get("opacity");case"float":l=a;}l=l.camelCase();var f=this.style[l];if(!f||l=="zIndex"){f=[]; +for(var k in Element.ShortStyles){if(l!=k){continue;}for(var j in Element.ShortStyles[k]){f.push(this.getStyle(j));}return f.join(" ");}f=this.getComputedStyle(l); +}if(f){f=String(f);var h=f.match(/rgba?\([\d\s,]+\)/);if(h){f=f.replace(h[0],h[0].rgbToHex());}}if(Browser.opera||(Browser.ie&&isNaN(parseFloat(f)))){if((/^(height|width)$/).test(l)){var g=(l=="width")?["left","right"]:["top","bottom"],i=0; +g.each(function(m){i+=this.getStyle("border-"+m+"-width").toInt()+this.getStyle("padding-"+m).toInt();},this);return this["offset"+l.capitalize()]-i+"px"; +}if(Browser.opera&&String(f).indexOf("px")!=-1){return f;}if((/^border(.+)Width|margin|padding/).test(l)){return"0px";}}return f;},setStyles:function(g){for(var f in g){this.setStyle(f,g[f]); +}return this;},getStyles:function(){var f={};Array.flatten(arguments).each(function(g){f[g]=this.getStyle(g);},this);return f;}});Element.Styles={left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"}; +Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(l){var k=Element.ShortStyles; +var g=Element.Styles;["margin","padding"].each(function(m){var n=m+l;k[m][n]=g[n]="@px";});var j="border"+l;k.border[j]=g[j]="@px @ rgb(@, @, @)";var i=j+"Width",f=j+"Style",h=j+"Color"; +k[j]={};k.borderWidth[i]=k[j][i]=g[i]="@px";k.borderStyle[f]=k[j][f]=g[f]="@";k.borderColor[h]=k[j][h]=g[h]="rgb(@, @, @)";});})();(function(){Element.Properties.events={set:function(b){this.addEvents(b); +}};[Element,Window,Document].invoke("implement",{addEvent:function(f,h){var i=this.retrieve("events",{});if(!i[f]){i[f]={keys:[],values:[]};}if(i[f].keys.contains(h)){return this; +}i[f].keys.push(h);var g=f,b=Element.Events[f],d=h,j=this;if(b){if(b.onAdd){b.onAdd.call(this,h);}if(b.condition){d=function(k){if(b.condition.call(this,k)){return h.call(this,k); +}return true;};}g=b.base||g;}var e=function(){return h.call(j);};var c=Element.NativeEvents[g];if(c){if(c==2){e=function(k){k=new Event(k,j.getWindow()); +if(d.call(j,k)===false){k.stop();}};}this.addListener(g,e,arguments[2]);}i[f].values.push(e);return this;},removeEvent:function(e,d){var c=this.retrieve("events"); +if(!c||!c[e]){return this;}var h=c[e];var b=h.keys.indexOf(d);if(b==-1){return this;}var g=h.values[b];delete h.keys[b];delete h.values[b];var f=Element.Events[e]; +if(f){if(f.onRemove){f.onRemove.call(this,d);}e=f.base||e;}return(Element.NativeEvents[e])?this.removeListener(e,g,arguments[2]):this;},addEvents:function(b){for(var c in b){this.addEvent(c,b[c]); +}return this;},removeEvents:function(b){var d;if(typeOf(b)=="object"){for(d in b){this.removeEvent(d,b[d]);}return this;}var c=this.retrieve("events"); +if(!c){return this;}if(!b){for(d in c){this.removeEvents(d);}this.eliminate("events");}else{if(c[b]){c[b].keys.each(function(e){this.removeEvent(b,e);},this); +delete c[b];}}return this;},fireEvent:function(e,c,b){var d=this.retrieve("events");if(!d||!d[e]){return this;}c=Array.from(c);d[e].keys.each(function(f){if(b){f.delay(b,this,c); +}else{f.apply(this,c);}},this);return this;},cloneEvents:function(e,d){e=document.id(e);var c=e.retrieve("events");if(!c){return this;}if(!d){for(var b in c){this.cloneEvents(e,b); +}}else{if(c[d]){c[d].keys.each(function(f){this.addEvent(d,f);},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,orientationchange:2,touchstart:2,touchmove:2,touchend:2,touchcancel:2,gesturestart:2,gesturechange:2,gestureend:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:2,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1}; +var a=function(b){var c=b.relatedTarget;if(c==null){return true;}if(!c){return false;}return(c!=this&&c.prefix!="xul"&&typeOf(this)!="document"&&!this.contains(c)); +};Element.Events={mouseenter:{base:"mouseover",condition:a},mouseleave:{base:"mouseout",condition:a},mousewheel:{base:(Browser.firefox)?"DOMMouseScroll":"mousewheel"}}; +})();(function(){var h=document.createElement("div"),e=document.createElement("div");h.style.height="0";h.appendChild(e);var d=(e.offsetParent===h);h=e=null; +var l=function(m){return k(m,"position")!="static"||a(m);};var i=function(m){return l(m)||(/^(?:table|td|th)$/i).test(m.tagName);};Element.implement({scrollTo:function(m,n){if(a(this)){this.getWindow().scrollTo(m,n); +}else{this.scrollLeft=m;this.scrollTop=n;}return this;},getSize:function(){if(a(this)){return this.getWindow().getSize();}return{x:this.offsetWidth,y:this.offsetHeight}; +},getScrollSize:function(){if(a(this)){return this.getWindow().getScrollSize();}return{x:this.scrollWidth,y:this.scrollHeight};},getScroll:function(){if(a(this)){return this.getWindow().getScroll(); +}return{x:this.scrollLeft,y:this.scrollTop};},getScrolls:function(){var n=this.parentNode,m={x:0,y:0};while(n&&!a(n)){m.x+=n.scrollLeft;m.y+=n.scrollTop; +n=n.parentNode;}return m;},getOffsetParent:d?function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}var n=(k(m,"position")=="static")?i:l; +while((m=m.parentNode)){if(n(m)){return m;}}return null;}:function(){var m=this;if(a(m)||k(m,"position")=="fixed"){return null;}try{return m.offsetParent; +}catch(n){}return null;},getOffsets:function(){if(this.getBoundingClientRect&&!Browser.Platform.ios){var r=this.getBoundingClientRect(),o=document.id(this.getDocument().documentElement),q=o.getScroll(),t=this.getScrolls(),s=(k(this,"position")=="fixed"); +return{x:r.left.toInt()+t.x+((s)?0:q.x)-o.clientLeft,y:r.top.toInt()+t.y+((s)?0:q.y)-o.clientTop};}var n=this,m={x:0,y:0};if(a(this)){return m;}while(n&&!a(n)){m.x+=n.offsetLeft; +m.y+=n.offsetTop;if(Browser.firefox){if(!c(n)){m.x+=b(n);m.y+=g(n);}var p=n.parentNode;if(p&&k(p,"overflow")!="visible"){m.x+=b(p);m.y+=g(p);}}else{if(n!=this&&Browser.safari){m.x+=b(n); +m.y+=g(n);}}n=n.offsetParent;}if(Browser.firefox&&!c(this)){m.x-=b(this);m.y-=g(this);}return m;},getPosition:function(p){if(a(this)){return{x:0,y:0};}var q=this.getOffsets(),n=this.getScrolls(); +var m={x:q.x-n.x,y:q.y-n.y};if(p&&(p=document.id(p))){var o=p.getPosition();return{x:m.x-o.x-b(p),y:m.y-o.y-g(p)};}return m;},getCoordinates:function(o){if(a(this)){return this.getWindow().getCoordinates(); +}var m=this.getPosition(o),n=this.getSize();var p={left:m.x,top:m.y,width:n.x,height:n.y};p.right=p.left+p.width;p.bottom=p.top+p.height;return p;},computePosition:function(m){return{left:m.x-j(this,"margin-left"),top:m.y-j(this,"margin-top")}; +},setPosition:function(m){return this.setStyles(this.computePosition(m));}});[Document,Window].invoke("implement",{getSize:function(){var m=f(this);return{x:m.clientWidth,y:m.clientHeight}; +},getScroll:function(){var n=this.getWindow(),m=f(this);return{x:n.pageXOffset||m.scrollLeft,y:n.pageYOffset||m.scrollTop};},getScrollSize:function(){var o=f(this),n=this.getSize(),m=this.getDocument().body; +return{x:Math.max(o.scrollWidth,m.scrollWidth,n.x),y:Math.max(o.scrollHeight,m.scrollHeight,n.y)};},getPosition:function(){return{x:0,y:0};},getCoordinates:function(){var m=this.getSize(); +return{top:0,left:0,bottom:m.y,right:m.x,height:m.y,width:m.x};}});var k=Element.getComputedStyle;function j(m,n){return k(m,n).toInt()||0;}function c(m){return k(m,"-moz-box-sizing")=="border-box"; +}function g(m){return j(m,"border-top-width");}function b(m){return j(m,"border-left-width");}function a(m){return(/^(?:body|html)$/i).test(m.tagName); +}function f(m){var n=m.getDocument();return(!n.compatMode||n.compatMode=="CSS1Compat")?n.html:n.body;}})();Element.alias({position:"setPosition"});[Window,Document,Element].invoke("implement",{getHeight:function(){return this.getSize().y; +},getWidth:function(){return this.getSize().x;},getScrollTop:function(){return this.getScroll().y;},getScrollLeft:function(){return this.getScroll().x; +},getScrollHeight:function(){return this.getScrollSize().y;},getScrollWidth:function(){return this.getScrollSize().x;},getTop:function(){return this.getPosition().y; +},getLeft:function(){return this.getPosition().x;}});(function(){var f=this.Fx=new Class({Implements:[Chain,Events,Options],options:{fps:60,unit:false,duration:500,frames:null,frameSkip:true,link:"ignore"},initialize:function(g){this.subject=this.subject||this; +this.setOptions(g);},getTransition:function(){return function(g){return -(Math.cos(Math.PI*g)-1)/2;};},step:function(g){if(this.options.frameSkip){var h=(this.time!=null)?(g-this.time):0,i=h/this.frameInterval; +this.time=g;this.frame+=i;}else{this.frame++;}if(this.frame=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);break;}}return e; +},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a&&a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,a+2); +});});(function(){var d=function(){},a=("onprogress" in new Browser.Request);var c=this.Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,timeout:0,noCache:false},initialize:function(e){this.xhr=new Browser.Request(); +this.setOptions(e);this.headers=this.options.headers;},onStateChange:function(){var e=this.xhr;if(e.readyState!=4||!this.running){return;}this.running=false; +this.status=0;Function.attempt(function(){var f=e.status;this.status=(f==1223)?204:f;}.bind(this));e.onreadystatechange=d;if(a){e.onprogress=e.onloadstart=d; +}clearTimeout(this.timer);this.response={text:this.xhr.responseText||"",xml:this.xhr.responseXML};if(this.options.isSuccess.call(this,this.status)){this.success(this.response.text,this.response.xml); +}else{this.failure();}},isSuccess:function(){var e=this.status;return(e>=200&&e<300);},isRunning:function(){return !!this.running;},processScripts:function(e){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return Browser.exec(e); +}return e.stripScripts(this.options.evalScripts);},success:function(f,e){this.onSuccess(this.processScripts(f),e);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain(); +},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},loadstart:function(e){this.fireEvent("loadstart",[e,this.xhr]); +},progress:function(e){this.fireEvent("progress",[e,this.xhr]);},timeout:function(){this.fireEvent("timeout",this.xhr);},setHeader:function(e,f){this.headers[e]=f; +return this;},getHeader:function(e){return Function.attempt(function(){return this.xhr.getResponseHeader(e);}.bind(this));},check:function(){if(!this.running){return true; +}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.pass(arguments,this));return false;}return false;},send:function(o){if(!this.check(o)){return this; +}this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.running=true;var l=typeOf(o);if(l=="string"||l=="element"){o={data:o};}var h=this.options; +o=Object.append({data:h.data,url:h.url,method:h.method},o);var j=o.data,f=String(o.url),e=o.method.toLowerCase();switch(typeOf(j)){case"element":j=document.id(j).toQueryString(); +break;case"object":case"hash":j=Object.toQueryString(j);}if(this.options.format){var m="format="+this.options.format;j=(j)?m+"&"+j:m;}if(this.options.emulation&&!["get","post"].contains(e)){var k="_method="+e; +j=(j)?k+"&"+j:k;e="post";}if(this.options.urlEncoded&&["post","put"].contains(e)){var g=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers["Content-type"]="application/x-www-form-urlencoded"+g; +}if(!f){f=document.location.pathname;}var i=f.lastIndexOf("/");if(i>-1&&(i=f.indexOf("#"))>-1){f=f.substr(0,i);}if(this.options.noCache){f+=(f.contains("?")?"&":"?")+String.uniqueID(); +}if(j&&e=="get"){f+=(f.contains("?")?"&":"?")+j;j=null;}var n=this.xhr;if(a){n.onloadstart=this.loadstart.bind(this);n.onprogress=this.progress.bind(this); +}n.open(e.toUpperCase(),f,this.options.async,this.options.user,this.options.password);if(this.options.user&&"withCredentials" in n){n.withCredentials=true; +}n.onreadystatechange=this.onStateChange.bind(this);Object.each(this.headers,function(q,p){try{n.setRequestHeader(p,q);}catch(r){this.fireEvent("exception",[p,q]); +}},this);this.fireEvent("request");n.send(j);if(!this.options.async){this.onStateChange();}if(this.options.timeout){this.timer=this.timeout.delay(this.options.timeout,this); +}return this;},cancel:function(){if(!this.running){return this;}this.running=false;var e=this.xhr;e.abort();clearTimeout(this.timer);e.onreadystatechange=d; +if(a){e.onprogress=e.onloadstart=d;}this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});var b={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(e){b[e]=function(g){var f={method:e}; +if(g!=null){f.data=g;}return this.send(f);};});c.implement(b);Element.Properties.send={set:function(e){var f=this.get("send").cancel();f.setOptions(e); +return this;},get:function(){var e=this.retrieve("send");if(!e){e=new c({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")}); +this.store("send",e);}return e;}};Element.implement({send:function(e){var f=this.get("send");f.send({data:this,url:e||f.options.url});return this;}});})(); +Request.HTML=new Class({Extends:Request,options:{update:false,append:false,evalScripts:true,filter:false,headers:{Accept:"text/html, application/xml, text/xml, */*"}},success:function(e){var d=this.options,b=this.response; +b.html=e.stripScripts(function(f){b.javascript=f;});var c=b.html.match(/]*>([\s\S]*?)<\/body>/i);if(c){b.html=c[1];}var a=new Element("div").set("html",b.html); +b.tree=a.childNodes;b.elements=a.getElements("*");if(d.filter){b.tree=b.elements.filter(d.filter);}if(d.update){document.id(d.update).empty().set("html",b.html); +}else{if(d.append){document.id(d.append).adopt(a.getChildren());}}if(d.evalScripts){Browser.exec(b.javascript);}this.onSuccess(b.tree,b.elements,b.html,b.javascript); +}});Element.Properties.load={set:function(a){var b=this.get("load").cancel();b.setOptions(a);return this;},get:function(){var a=this.retrieve("load");if(!a){a=new Request.HTML({data:this,link:"cancel",update:this,method:"get"}); +this.store("load",a);}return a;}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Type.isObject,url:Type.isString})); +return this;}});if(typeof JSON=="undefined"){this.JSON={};}(function(){var special={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"}; +var escape=function(chr){return special[chr]||"\\u"+("0000"+chr.charCodeAt(0).toString(16)).slice(-4);};JSON.validate=function(string){string=string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""); +return(/^[\],:{}\s]*$/).test(string);};JSON.encode=JSON.stringify?function(obj){return JSON.stringify(obj);}:function(obj){if(obj&&obj.toJSON){obj=obj.toJSON(); +}switch(typeOf(obj)){case"string":return'"'+obj.replace(/[\x00-\x1f\\"]/g,escape)+'"';case"array":return"["+obj.map(JSON.encode).clean()+"]";case"object":case"hash":var string=[]; +Object.each(obj,function(value,key){var json=JSON.encode(value);if(json){string.push(JSON.encode(key)+":"+json);}});return"{"+string+"}";case"number":case"boolean":return""+obj; +case"null":return"null";}return null;};JSON.decode=function(string,secure){if(!string||typeOf(string)!="string"){return null;}if(secure||JSON.secure){if(JSON.parse){return JSON.parse(string); +}if(!JSON.validate(string)){throw new Error("JSON could not decode the input; security is enabled and the value is not secure.");}}return eval("("+string+")"); +};})();Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(a){this.parent(a);Object.append(this.headers,{Accept:"application/json","X-Request":"JSON"}); +},success:function(c){var b;try{b=this.response.json=JSON.decode(c,this.options.secure);}catch(a){this.fireEvent("error",[c,a]);return;}if(b==null){this.onFailure(); +}else{this.onSuccess(b,c);}}});var Cookie=new Class({Implements:Options,options:{path:"/",domain:false,duration:false,secure:false,document:document,encode:true},initialize:function(b,a){this.key=b; +this.setOptions(a);},write:function(b){if(this.options.encode){b=encodeURIComponent(b);}if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path; +}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure"; +}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)"); +return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,Object.merge({},this.options,{duration:-1})).write("");return this;}}); +Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose(); +};(function(i,k){var l,f,e=[],c,b,d=k.createElement("div");var g=function(){clearTimeout(b);if(l){return;}Browser.loaded=l=true;k.removeListener("DOMContentLoaded",g).removeListener("readystatechange",a); +k.fireEvent("domready");i.fireEvent("domready");};var a=function(){for(var m=e.length;m--;){if(e[m]()){g();return true;}}return false;};var j=function(){clearTimeout(b); +if(!a()){b=setTimeout(j,10);}};k.addListener("DOMContentLoaded",g);var h=function(){try{d.doScroll();return true;}catch(m){}return false;};if(d.doScroll&&!h()){e.push(h); +c=true;}if(k.readyState){e.push(function(){var m=k.readyState;return(m=="loaded"||m=="complete");});}if("onreadystatechange" in k){k.addListener("readystatechange",a); +}else{c=true;}if(c){j();}Element.Events.domready={onAdd:function(m){if(l){m.call(this);}}};Element.Events.load={base:"load",onAdd:function(m){if(f&&this==i){m.call(this); +}},condition:function(){if(this==i){g();delete Element.Events.load;}return true;}};i.addEvent("load",function(){f=true;});})(window,document);(function(){var Swiff=this.Swiff=new Class({Implements:Options,options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"window",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object; +},initialize:function(path,options){this.instance="Swiff_"+String.uniqueID();this.setOptions(options);options=this.options;var id=this.id=options.id||this.instance; +var container=document.id(options.container);Swiff.CallBacks[this.instance]={};var params=options.params,vars=options.vars,callBacks=options.callBacks; +var properties=Object.append({height:options.height,width:options.width},options.properties);var self=this;for(var callBack in callBacks){Swiff.CallBacks[this.instance][callBack]=(function(option){return function(){return option.apply(self.object,arguments); +};})(callBacks[callBack]);vars[callBack]="Swiff.CallBacks."+this.instance+"."+callBack;}params.flashVars=Object.toQueryString(vars);if(Browser.ie){properties.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"; +params.movie=path;}else{properties.type="application/x-shockwave-flash";}properties.data=path;var build='';}}build+="";this.object=((container)?container.empty():new Element("div")).set("html",build).firstChild; +},replaces:function(element){element=document.id(element,true);element.parentNode.replaceChild(this.toElement(),element);return this;},inject:function(element){document.id(element,true).appendChild(this.toElement()); +return this;},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].append(arguments));}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction(''+__flash__argumentsToXML(arguments,2)+""); +return eval(rs);};})(); \ No newline at end of file diff --git a/web/tools/mootools/mootools-more-1.3.2.1-nc.js b/web/tools/mootools/mootools-more-1.3.2.1-nc.js new file mode 100644 index 000000000..4bf490e79 --- /dev/null +++ b/web/tools/mootools/mootools-more-1.3.2.1-nc.js @@ -0,0 +1,10042 @@ +// MooTools: the javascript framework. +// Load this file's selection again by visiting: http://mootools.net/more/09f3e47813269cd5026cbf8c1f828e72 +// Or build this file again with packager using: packager build More/Chain.Wait More/Array.Extras More/Date More/Date.Extras More/Number.Format More/String.Extras More/String.QueryString More/URI More/URI.Relative More/Hash More/Hash.Extras More/Element.Forms More/Elements.From More/Element.Event.Pseudos.Keys More/Element.Pin More/Element.Position More/Element.Shortcuts More/Form.Request More/Form.Request.Append More/Form.Validator.Inline More/Form.Validator.Extras More/OverText More/Fx.Accordion More/Fx.Move More/Fx.Reveal More/Fx.Slide More/Fx.SmoothScroll More/Fx.Sort More/Drag.Move More/Slider More/Sortables More/Request.JSONP More/Request.Queue More/Request.Periodical More/Assets More/Color More/Group More/Hash.Cookie More/Table More/HtmlTable.Zebra More/HtmlTable.Sort More/HtmlTable.Select More/Keyboard.Extras More/Mask More/Scroller More/Tips More/Locale.en-GB.Date +/* +--- + +script: More.js + +name: More + +description: MooTools More + +license: MIT-style license + +authors: + - Guillermo Rauch + - Thomas Aylott + - Scott Kyle + - Arian Stolwijk + - Tim Wienk + - Christoph Pojer + - Aaron Newton + - Jacob Thornton + +requires: + - Core/MooTools + +provides: [MooTools.More] + +... +*/ + +MooTools.More = { + 'version': '1.3.2.1', + 'build': 'e586bcd2496e9b22acfde32e12f84d49ce09e59d' +}; + + +/* +--- + +script: Chain.Wait.js + +name: Chain.Wait + +description: value, Adds a method to inject pauses between chained events. + +license: MIT-style license. + +authors: + - Aaron Newton + +requires: + - Core/Chain + - Core/Element + - Core/Fx + - /MooTools.More + +provides: [Chain.Wait] + +... +*/ + +(function(){ + + var wait = { + wait: function(duration){ + return this.chain(function(){ + this.callChain.delay(duration == null ? 500 : duration, this); + return this; + }.bind(this)); + } + }; + + Chain.implement(wait); + + if (this.Fx) Fx.implement(wait); + + if (this.Element && Element.implement && this.Fx){ + Element.implement({ + + chains: function(effects){ + Array.from(effects || ['tween', 'morph', 'reveal']).each(function(effect){ + effect = this.get(effect); + if (!effect) return; + effect.setOptions({ + link:'chain' + }); + }, this); + return this; + }, + + pauseFx: function(duration, effect){ + this.chains(effect).get(effect || 'tween').wait(duration); + return this; + } + + }); + } + +})(); + + +/* +--- + +script: Array.Extras.js + +name: Array.Extras + +description: Extends the Array native object to include useful methods to work with arrays. + +license: MIT-style license + +authors: + - Christoph Pojer + - Sebastian MarkbÃ¥ge + +requires: + - Core/Array + - MooTools.More + +provides: [Array.Extras] + +... +*/ + +(function(nil){ + +Array.implement({ + + min: function(){ + return Math.min.apply(null, this); + }, + + max: function(){ + return Math.max.apply(null, this); + }, + + average: function(){ + return this.length ? this.sum() / this.length : 0; + }, + + sum: function(){ + var result = 0, l = this.length; + if (l){ + while (l--) result += this[l]; + } + return result; + }, + + unique: function(){ + return [].combine(this); + }, + + shuffle: function(){ + for (var i = this.length; i && --i;){ + var temp = this[i], r = Math.floor(Math.random() * ( i + 1 )); + this[i] = this[r]; + this[r] = temp; + } + return this; + }, + + reduce: function(fn, value){ + for (var i = 0, l = this.length; i < l; i++){ + if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this); + } + return value; + }, + + reduceRight: function(fn, value){ + var i = this.length; + while (i--){ + if (i in this) value = value === nil ? this[i] : fn.call(null, value, this[i], i, this); + } + return value; + } + +}); + +})(); + + +/* +--- + +script: Object.Extras.js + +name: Object.Extras + +description: Extra Object generics, like getFromPath which allows a path notation to child elements. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Object + - /MooTools.More + +provides: [Object.Extras] + +... +*/ + +(function(){ + +var defined = function(value){ + return value != null; +}; + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +Object.extend({ + + getFromPath: function(source, parts){ + if (typeof parts == 'string') parts = parts.split('.'); + for (var i = 0, l = parts.length; i < l; i++){ + if (hasOwnProperty.call(source, parts[i])) source = source[parts[i]]; + else return null; + } + return source; + }, + + cleanValues: function(object, method){ + method = method || defined; + for (var key in object) if (!method(object[key])){ + delete object[key]; + } + return object; + }, + + erase: function(object, key){ + if (hasOwnProperty.call(object, key)) delete object[key]; + return object; + }, + + run: function(object){ + var args = Array.slice(arguments, 1); + for (var key in object) if (object[key].apply){ + object[key].apply(object, args); + } + return object; + } + +}); + +})(); + + +/* +--- + +script: Locale.js + +name: Locale + +description: Provides methods for localization. + +license: MIT-style license + +authors: + - Aaron Newton + - Arian Stolwijk + +requires: + - Core/Events + - /Object.Extras + - /MooTools.More + +provides: [Locale, Lang] + +... +*/ + +(function(){ + +var current = null, + locales = {}, + inherits = {}; + +var getSet = function(set){ + if (instanceOf(set, Locale.Set)) return set; + else return locales[set]; +}; + +var Locale = this.Locale = { + + define: function(locale, set, key, value){ + var name; + if (instanceOf(locale, Locale.Set)){ + name = locale.name; + if (name) locales[name] = locale; + } else { + name = locale; + if (!locales[name]) locales[name] = new Locale.Set(name); + locale = locales[name]; + } + + if (set) locale.define(set, key, value); + + + + if (!current) current = locale; + + return locale; + }, + + use: function(locale){ + locale = getSet(locale); + + if (locale){ + current = locale; + + this.fireEvent('change', locale); + + + } + + return this; + }, + + getCurrent: function(){ + return current; + }, + + get: function(key, args){ + return (current) ? current.get(key, args) : ''; + }, + + inherit: function(locale, inherits, set){ + locale = getSet(locale); + + if (locale) locale.inherit(inherits, set); + return this; + }, + + list: function(){ + return Object.keys(locales); + } + +}; + +Object.append(Locale, new Events); + +Locale.Set = new Class({ + + sets: {}, + + inherits: { + locales: [], + sets: {} + }, + + initialize: function(name){ + this.name = name || ''; + }, + + define: function(set, key, value){ + var defineData = this.sets[set]; + if (!defineData) defineData = {}; + + if (key){ + if (typeOf(key) == 'object') defineData = Object.merge(defineData, key); + else defineData[key] = value; + } + this.sets[set] = defineData; + + return this; + }, + + get: function(key, args, _base){ + var value = Object.getFromPath(this.sets, key); + if (value != null){ + var type = typeOf(value); + if (type == 'function') value = value.apply(null, Array.from(args)); + else if (type == 'object') value = Object.clone(value); + return value; + } + + // get value of inherited locales + var index = key.indexOf('.'), + set = index < 0 ? key : key.substr(0, index), + names = (this.inherits.sets[set] || []).combine(this.inherits.locales).include('en-US'); + if (!_base) _base = []; + + for (var i = 0, l = names.length; i < l; i++){ + if (_base.contains(names[i])) continue; + _base.include(names[i]); + + var locale = locales[names[i]]; + if (!locale) continue; + + value = locale.get(key, args, _base); + if (value != null) return value; + } + + return ''; + }, + + inherit: function(names, set){ + names = Array.from(names); + + if (set && !this.inherits.sets[set]) this.inherits.sets[set] = []; + + var l = names.length; + while (l--) (set ? this.inherits.sets[set] : this.inherits.locales).unshift(names[l]); + + return this; + } + +}); + + + +})(); + + +/* +--- + +name: Locale.en-US.Date + +description: Date messages for US English. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Locale + +provides: [Locale.en-US.Date] + +... +*/ + +Locale.define('en-US', 'Date', { + + months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'], + months_abbr: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + days_abbr: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + + // Culture's date order: MM/DD/YYYY + dateOrder: ['month', 'date', 'year'], + shortDate: '%m/%d/%Y', + shortTime: '%I:%M%p', + AM: 'AM', + PM: 'PM', + firstDayOfWeek: 0, + + // Date.Extras + ordinal: function(dayOfMonth){ + // 1st, 2nd, 3rd, etc. + return (dayOfMonth > 3 && dayOfMonth < 21) ? 'th' : ['th', 'st', 'nd', 'rd', 'th'][Math.min(dayOfMonth % 10, 4)]; + }, + + lessThanMinuteAgo: 'less than a minute ago', + minuteAgo: 'about a minute ago', + minutesAgo: '{delta} minutes ago', + hourAgo: 'about an hour ago', + hoursAgo: 'about {delta} hours ago', + dayAgo: '1 day ago', + daysAgo: '{delta} days ago', + weekAgo: '1 week ago', + weeksAgo: '{delta} weeks ago', + monthAgo: '1 month ago', + monthsAgo: '{delta} months ago', + yearAgo: '1 year ago', + yearsAgo: '{delta} years ago', + + lessThanMinuteUntil: 'less than a minute from now', + minuteUntil: 'about a minute from now', + minutesUntil: '{delta} minutes from now', + hourUntil: 'about an hour from now', + hoursUntil: 'about {delta} hours from now', + dayUntil: '1 day from now', + daysUntil: '{delta} days from now', + weekUntil: '1 week from now', + weeksUntil: '{delta} weeks from now', + monthUntil: '1 month from now', + monthsUntil: '{delta} months from now', + yearUntil: '1 year from now', + yearsUntil: '{delta} years from now' + +}); + + +/* +--- + +script: Date.js + +name: Date + +description: Extends the Date native object to include methods useful in managing dates. + +license: MIT-style license + +authors: + - Aaron Newton + - Nicholas Barthelemy - https://svn.nbarthelemy.com/date-js/ + - Harald Kirshner - mail [at] digitarald.de; http://digitarald.de + - Scott Kyle - scott [at] appden.com; http://appden.com + +requires: + - Core/Array + - Core/String + - Core/Number + - MooTools.More + - Locale + - Locale.en-US.Date + +provides: [Date] + +... +*/ + +(function(){ + +var Date = this.Date; + +var DateMethods = Date.Methods = { + ms: 'Milliseconds', + year: 'FullYear', + min: 'Minutes', + mo: 'Month', + sec: 'Seconds', + hr: 'Hours' +}; + +['Date', 'Day', 'FullYear', 'Hours', 'Milliseconds', 'Minutes', 'Month', 'Seconds', 'Time', 'TimezoneOffset', + 'Week', 'Timezone', 'GMTOffset', 'DayOfYear', 'LastMonth', 'LastDayOfMonth', 'UTCDate', 'UTCDay', 'UTCFullYear', + 'AMPM', 'Ordinal', 'UTCHours', 'UTCMilliseconds', 'UTCMinutes', 'UTCMonth', 'UTCSeconds', 'UTCMilliseconds'].each(function(method){ + Date.Methods[method.toLowerCase()] = method; +}); + +var pad = function(n, digits, string){ + if (digits == 1) return n; + return n < Math.pow(10, digits - 1) ? (string || '0') + pad(n, digits - 1, string) : n; +}; + +Date.implement({ + + set: function(prop, value){ + prop = prop.toLowerCase(); + var method = DateMethods[prop] && 'set' + DateMethods[prop]; + if (method && this[method]) this[method](value); + return this; + }.overloadSetter(), + + get: function(prop){ + prop = prop.toLowerCase(); + var method = DateMethods[prop] && 'get' + DateMethods[prop]; + if (method && this[method]) return this[method](); + return null; + }.overloadGetter(), + + clone: function(){ + return new Date(this.get('time')); + }, + + increment: function(interval, times){ + interval = interval || 'day'; + times = times != null ? times : 1; + + switch (interval){ + case 'year': + return this.increment('month', times * 12); + case 'month': + var d = this.get('date'); + this.set('date', 1).set('mo', this.get('mo') + times); + return this.set('date', d.min(this.get('lastdayofmonth'))); + case 'week': + return this.increment('day', times * 7); + case 'day': + return this.set('date', this.get('date') + times); + } + + if (!Date.units[interval]) throw new Error(interval + ' is not a supported interval'); + + return this.set('time', this.get('time') + times * Date.units[interval]()); + }, + + decrement: function(interval, times){ + return this.increment(interval, -1 * (times != null ? times : 1)); + }, + + isLeapYear: function(){ + return Date.isLeapYear(this.get('year')); + }, + + clearTime: function(){ + return this.set({hr: 0, min: 0, sec: 0, ms: 0}); + }, + + diff: function(date, resolution){ + if (typeOf(date) == 'string') date = Date.parse(date); + + return ((date - this) / Date.units[resolution || 'day'](3, 3)).round(); // non-leap year, 30-day month + }, + + getLastDayOfMonth: function(){ + return Date.daysInMonth(this.get('mo'), this.get('year')); + }, + + getDayOfYear: function(){ + return (Date.UTC(this.get('year'), this.get('mo'), this.get('date') + 1) + - Date.UTC(this.get('year'), 0, 1)) / Date.units.day(); + }, + + setDay: function(day, firstDayOfWeek){ + if (firstDayOfWeek == null){ + firstDayOfWeek = Date.getMsg('firstDayOfWeek'); + if (firstDayOfWeek === '') firstDayOfWeek = 1; + } + + day = (7 + Date.parseDay(day, true) - firstDayOfWeek) % 7; + var currentDay = (7 + this.get('day') - firstDayOfWeek) % 7; + + return this.increment('day', day - currentDay); + }, + + getWeek: function(firstDayOfWeek){ + if (firstDayOfWeek == null){ + firstDayOfWeek = Date.getMsg('firstDayOfWeek'); + if (firstDayOfWeek === '') firstDayOfWeek = 1; + } + + var date = this, + dayOfWeek = (7 + date.get('day') - firstDayOfWeek) % 7, + dividend = 0, + firstDayOfYear; + + if (firstDayOfWeek == 1){ + // ISO-8601, week belongs to year that has the most days of the week (i.e. has the thursday of the week) + var month = date.get('month'), + startOfWeek = date.get('date') - dayOfWeek; + + if (month == 11 && startOfWeek > 28) return 1; // Week 1 of next year + + if (month == 0 && startOfWeek < -2){ + // Use a date from last year to determine the week + date = new Date(date).decrement('day', dayOfWeek); + dayOfWeek = 0; + } + + firstDayOfYear = new Date(date.get('year'), 0, 1).get('day') || 7; + if (firstDayOfYear > 4) dividend = -7; // First week of the year is not week 1 + } else { + // In other cultures the first week of the year is always week 1 and the last week always 53 or 54. + // Days in the same week can have a different weeknumber if the week spreads across two years. + firstDayOfYear = new Date(date.get('year'), 0, 1).get('day'); + } + + dividend += date.get('dayofyear'); + dividend += 6 - dayOfWeek; // Add days so we calculate the current date's week as a full week + dividend += (7 + firstDayOfYear - firstDayOfWeek) % 7; // Make up for first week of the year not being a full week + + return (dividend / 7); + }, + + getOrdinal: function(day){ + return Date.getMsg('ordinal', day || this.get('date')); + }, + + getTimezone: function(){ + return this.toString() + .replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/, '$1') + .replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/, '$1$2$3'); + }, + + getGMTOffset: function(){ + var off = this.get('timezoneOffset'); + return ((off > 0) ? '-' : '+') + pad((off.abs() / 60).floor(), 2) + pad(off % 60, 2); + }, + + setAMPM: function(ampm){ + ampm = ampm.toUpperCase(); + var hr = this.get('hr'); + if (hr > 11 && ampm == 'AM') return this.decrement('hour', 12); + else if (hr < 12 && ampm == 'PM') return this.increment('hour', 12); + return this; + }, + + getAMPM: function(){ + return (this.get('hr') < 12) ? 'AM' : 'PM'; + }, + + parse: function(str){ + this.set('time', Date.parse(str)); + return this; + }, + + isValid: function(date){ + return !isNaN((date || this).valueOf()); + }, + + format: function(f){ + if (!this.isValid()) return 'invalid date'; + if (!f) f = '%x %X'; + + var formatLower = f.toLowerCase(); + if (formatters[formatLower]) return formatters[formatLower](this); // it's a formatter! + f = formats[formatLower] || f; // replace short-hand with actual format + + var d = this; + return f.replace(/%([a-z%])/gi, + function($0, $1){ + switch ($1){ + case 'a': return Date.getMsg('days_abbr')[d.get('day')]; + case 'A': return Date.getMsg('days')[d.get('day')]; + case 'b': return Date.getMsg('months_abbr')[d.get('month')]; + case 'B': return Date.getMsg('months')[d.get('month')]; + case 'c': return d.format('%a %b %d %H:%M:%S %Y'); + case 'd': return pad(d.get('date'), 2); + case 'e': return pad(d.get('date'), 2, ' '); + case 'H': return pad(d.get('hr'), 2); + case 'I': return pad((d.get('hr') % 12) || 12, 2); + case 'j': return pad(d.get('dayofyear'), 3); + case 'k': return pad(d.get('hr'), 2, ' '); + case 'l': return pad((d.get('hr') % 12) || 12, 2, ' '); + case 'L': return pad(d.get('ms'), 3); + case 'm': return pad((d.get('mo') + 1), 2); + case 'M': return pad(d.get('min'), 2); + case 'o': return d.get('ordinal'); + case 'p': return Date.getMsg(d.get('ampm')); + case 's': return Math.round(d / 1000); + case 'S': return pad(d.get('seconds'), 2); + case 'T': return d.format('%H:%M:%S'); + case 'U': return pad(d.get('week'), 2); + case 'w': return d.get('day'); + case 'x': return d.format(Date.getMsg('shortDate')); + case 'X': return d.format(Date.getMsg('shortTime')); + case 'y': return d.get('year').toString().substr(2); + case 'Y': return d.get('year'); + case 'z': return d.get('GMTOffset'); + case 'Z': return d.get('Timezone'); + } + return $1; + } + ); + }, + + toISOString: function(){ + return this.format('iso8601'); + } + +}).alias({ + toJSON: 'toISOString', + compare: 'diff', + strftime: 'format' +}); + +var formats = { + db: '%Y-%m-%d %H:%M:%S', + compact: '%Y%m%dT%H%M%S', + 'short': '%d %b %H:%M', + 'long': '%B %d, %Y %H:%M' +}; + +// The day and month abbreviations are standardized, so we cannot use simply %a and %b because they will get localized +var rfcDayAbbr = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + rfcMonthAbbr = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + +var formatters = { + rfc822: function(date){ + return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %Z'); + }, + rfc2822: function(date){ + return rfcDayAbbr[date.get('day')] + date.format(', %d ') + rfcMonthAbbr[date.get('month')] + date.format(' %Y %H:%M:%S %z'); + }, + iso8601: function(date){ + return ( + date.getUTCFullYear() + '-' + + pad(date.getUTCMonth() + 1, 2) + '-' + + pad(date.getUTCDate(), 2) + 'T' + + pad(date.getUTCHours(), 2) + ':' + + pad(date.getUTCMinutes(), 2) + ':' + + pad(date.getUTCSeconds(), 2) + '.' + + pad(date.getUTCMilliseconds(), 3) + 'Z' + ); + } +}; + + +var parsePatterns = [], + nativeParse = Date.parse; + +var parseWord = function(type, word, num){ + var ret = -1, + translated = Date.getMsg(type + 's'); + switch (typeOf(word)){ + case 'object': + ret = translated[word.get(type)]; + break; + case 'number': + ret = translated[word]; + if (!ret) throw new Error('Invalid ' + type + ' index: ' + word); + break; + case 'string': + var match = translated.filter(function(name){ + return this.test(name); + }, new RegExp('^' + word, 'i')); + if (!match.length) throw new Error('Invalid ' + type + ' string'); + if (match.length > 1) throw new Error('Ambiguous ' + type); + ret = match[0]; + } + + return (num) ? translated.indexOf(ret) : ret; +}; + +var startCentury = 1900, + startYear = 70; + +Date.extend({ + + getMsg: function(key, args){ + return Locale.get('Date.' + key, args); + }, + + units: { + ms: Function.from(1), + second: Function.from(1000), + minute: Function.from(60000), + hour: Function.from(3600000), + day: Function.from(86400000), + week: Function.from(608400000), + month: function(month, year){ + var d = new Date; + return Date.daysInMonth(month != null ? month : d.get('mo'), year != null ? year : d.get('year')) * 86400000; + }, + year: function(year){ + year = year || new Date().get('year'); + return Date.isLeapYear(year) ? 31622400000 : 31536000000; + } + }, + + daysInMonth: function(month, year){ + return [31, Date.isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; + }, + + isLeapYear: function(year){ + return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0); + }, + + parse: function(from){ + var t = typeOf(from); + if (t == 'number') return new Date(from); + if (t != 'string') return from; + from = from.clean(); + if (!from.length) return null; + + var parsed; + parsePatterns.some(function(pattern){ + var bits = pattern.re.exec(from); + return (bits) ? (parsed = pattern.handler(bits)) : false; + }); + + if (!(parsed && parsed.isValid())){ + parsed = new Date(nativeParse(from)); + if (!(parsed && parsed.isValid())) parsed = new Date(from.toInt()); + } + return parsed; + }, + + parseDay: function(day, num){ + return parseWord('day', day, num); + }, + + parseMonth: function(month, num){ + return parseWord('month', month, num); + }, + + parseUTC: function(value){ + var localDate = new Date(value); + var utcSeconds = Date.UTC( + localDate.get('year'), + localDate.get('mo'), + localDate.get('date'), + localDate.get('hr'), + localDate.get('min'), + localDate.get('sec'), + localDate.get('ms') + ); + return new Date(utcSeconds); + }, + + orderIndex: function(unit){ + return Date.getMsg('dateOrder').indexOf(unit) + 1; + }, + + defineFormat: function(name, format){ + formats[name] = format; + return this; + }, + + defineFormats: function(formats){ + for (var name in formats) Date.defineFormat(name, formats[name]); + return this; + }, + + + + defineParser: function(pattern){ + parsePatterns.push((pattern.re && pattern.handler) ? pattern : build(pattern)); + return this; + }, + + defineParsers: function(){ + Array.flatten(arguments).each(Date.defineParser); + return this; + }, + + define2DigitYearStart: function(year){ + startYear = year % 100; + startCentury = year - startYear; + return this; + } + +}); + +var regexOf = function(type){ + return new RegExp('(?:' + Date.getMsg(type).map(function(name){ + return name.substr(0, 3); + }).join('|') + ')[a-z]*'); +}; + +var replacers = function(key){ + switch (key){ + case 'T': + return '%H:%M:%S'; + case 'x': // iso8601 covers yyyy-mm-dd, so just check if month is first + return ((Date.orderIndex('month') == 1) ? '%m[-./]%d' : '%d[-./]%m') + '([-./]%y)?'; + case 'X': + return '%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?'; + } + return null; +}; + +var keys = { + d: /[0-2]?[0-9]|3[01]/, + H: /[01]?[0-9]|2[0-3]/, + I: /0?[1-9]|1[0-2]/, + M: /[0-5]?\d/, + s: /\d+/, + o: /[a-z]*/, + p: /[ap]\.?m\.?/, + y: /\d{2}|\d{4}/, + Y: /\d{4}/, + z: /Z|[+-]\d{2}(?::?\d{2})?/ +}; + +keys.m = keys.I; +keys.S = keys.M; + +var currentLanguage; + +var recompile = function(language){ + currentLanguage = language; + + keys.a = keys.A = regexOf('days'); + keys.b = keys.B = regexOf('months'); + + parsePatterns.each(function(pattern, i){ + if (pattern.format) parsePatterns[i] = build(pattern.format); + }); +}; + +var build = function(format){ + if (!currentLanguage) return {format: format}; + + var parsed = []; + var re = (format.source || format) // allow format to be regex + .replace(/%([a-z])/gi, + function($0, $1){ + return replacers($1) || $0; + } + ).replace(/\((?!\?)/g, '(?:') // make all groups non-capturing + .replace(/ (?!\?|\*)/g, ',? ') // be forgiving with spaces and commas + .replace(/%([a-z%])/gi, + function($0, $1){ + var p = keys[$1]; + if (!p) return $1; + parsed.push($1); + return '(' + p.source + ')'; + } + ).replace(/\[a-z\]/gi, '[a-z\\u00c0-\\uffff;\&]'); // handle unicode words + + return { + format: format, + re: new RegExp('^' + re + '$', 'i'), + handler: function(bits){ + bits = bits.slice(1).associate(parsed); + var date = new Date().clearTime(), + year = bits.y || bits.Y; + + if (year != null) handle.call(date, 'y', year); // need to start in the right year + if ('d' in bits) handle.call(date, 'd', 1); + if ('m' in bits || bits.b || bits.B) handle.call(date, 'm', 1); + + for (var key in bits) handle.call(date, key, bits[key]); + return date; + } + }; +}; + +var handle = function(key, value){ + if (!value) return this; + + switch (key){ + case 'a': case 'A': return this.set('day', Date.parseDay(value, true)); + case 'b': case 'B': return this.set('mo', Date.parseMonth(value, true)); + case 'd': return this.set('date', value); + case 'H': case 'I': return this.set('hr', value); + case 'm': return this.set('mo', value - 1); + case 'M': return this.set('min', value); + case 'p': return this.set('ampm', value.replace(/\./g, '')); + case 'S': return this.set('sec', value); + case 's': return this.set('ms', ('0.' + value) * 1000); + case 'w': return this.set('day', value); + case 'Y': return this.set('year', value); + case 'y': + value = +value; + if (value < 100) value += startCentury + (value < startYear ? 100 : 0); + return this.set('year', value); + case 'z': + if (value == 'Z') value = '+00'; + var offset = value.match(/([+-])(\d{2}):?(\d{2})?/); + offset = (offset[1] + '1') * (offset[2] * 60 + (+offset[3] || 0)) + this.getTimezoneOffset(); + return this.set('time', this - offset * 60000); + } + + return this; +}; + +Date.defineParsers( + '%Y([-./]%m([-./]%d((T| )%X)?)?)?', // "1999-12-31", "1999-12-31 11:59pm", "1999-12-31 23:59:59", ISO8601 + '%Y%m%d(T%H(%M%S?)?)?', // "19991231", "19991231T1159", compact + '%x( %X)?', // "12/31", "12.31.99", "12-31-1999", "12/31/2008 11:59 PM" + '%d%o( %b( %Y)?)?( %X)?', // "31st", "31st December", "31 Dec 1999", "31 Dec 1999 11:59pm" + '%b( %d%o)?( %Y)?( %X)?', // Same as above with month and day switched + '%Y %b( %d%o( %X)?)?', // Same as above with year coming first + '%o %b %d %X %z %Y', // "Thu Oct 22 08:11:23 +0000 2009" + '%T', // %H:%M:%S + '%H:%M( ?%p)?' // "11:05pm", "11:05 am" and "11:05" +); + +Locale.addEvent('change', function(language){ + if (Locale.get('Date')) recompile(language); +}).fireEvent('change', Locale.getCurrent()); + +})(); + + +/* +--- + +script: Date.Extras.js + +name: Date.Extras + +description: Extends the Date native object to include extra methods (on top of those in Date.js). + +license: MIT-style license + +authors: + - Aaron Newton + - Scott Kyle + +requires: + - /Date + +provides: [Date.Extras] + +... +*/ + +Date.implement({ + + timeDiffInWords: function(to){ + return Date.distanceOfTimeInWords(this, to || new Date); + }, + + timeDiff: function(to, separator){ + if (to == null) to = new Date; + var delta = ((to - this) / 1000).floor().abs(); + + var vals = [], + durations = [60, 60, 24, 365, 0], + names = ['s', 'm', 'h', 'd', 'y'], + value, duration; + + for (var item = 0; item < durations.length; item++){ + if (item && !delta) break; + value = delta; + if ((duration = durations[item])){ + value = (delta % duration); + delta = (delta / duration).floor(); + } + vals.unshift(value + (names[item] || '')); + } + + return vals.join(separator || ':'); + } + +}).extend({ + + distanceOfTimeInWords: function(from, to){ + return Date.getTimePhrase(((to - from) / 1000).toInt()); + }, + + getTimePhrase: function(delta){ + var suffix = (delta < 0) ? 'Until' : 'Ago'; + if (delta < 0) delta *= -1; + + var units = { + minute: 60, + hour: 60, + day: 24, + week: 7, + month: 52 / 12, + year: 12, + eon: Infinity + }; + + var msg = 'lessThanMinute'; + + for (var unit in units){ + var interval = units[unit]; + if (delta < 1.5 * interval){ + if (delta > 0.75 * interval) msg = unit; + break; + } + delta /= interval; + msg = unit + 's'; + } + + delta = delta.round(); + return Date.getMsg(msg + suffix, delta).substitute({delta: delta}); + } + +}).defineParsers( + + { + // "today", "tomorrow", "yesterday" + re: /^(?:tod|tom|yes)/i, + handler: function(bits){ + var d = new Date().clearTime(); + switch (bits[0]){ + case 'tom': return d.increment(); + case 'yes': return d.decrement(); + default: return d; + } + } + }, + + { + // "next Wednesday", "last Thursday" + re: /^(next|last) ([a-z]+)$/i, + handler: function(bits){ + var d = new Date().clearTime(); + var day = d.getDay(); + var newDay = Date.parseDay(bits[2], true); + var addDays = newDay - day; + if (newDay <= day) addDays += 7; + if (bits[1] == 'last') addDays -= 7; + return d.set('date', d.getDate() + addDays); + } + } + +).alias('timeAgoInWords', 'timeDiffInWords'); + + +/* +--- + +name: Locale.en-US.Number + +description: Number messages for US English. + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: + - /Locale + +provides: [Locale.en-US.Number] + +... +*/ + +Locale.define('en-US', 'Number', { + + decimal: '.', + group: ',', + +/* Commented properties are the defaults for Number.format + decimals: 0, + precision: 0, + scientific: null, + + prefix: null, + suffic: null, + + // Negative/Currency/percentage will mixin Number + negative: { + prefix: '-' + },*/ + + currency: { +// decimals: 2, + prefix: '$ ' + }/*, + + percentage: { + decimals: 2, + suffix: '%' + }*/ + +}); + + + + +/* +--- +name: Number.Format +description: Extends the Number Type object to include a number formatting method. +license: MIT-style license +authors: [Arian Stolwijk] +requires: [Core/Number, Locale.en-US.Number] +# Number.Extras is for compatibility +provides: [Number.Format, Number.Extras] +... +*/ + + +Number.implement({ + + format: function(options){ + // Thanks dojo and YUI for some inspiration + var value = this; + options = options ? Object.clone(options) : {}; + var getOption = function(key){ + if (options[key] != null) return options[key]; + return Locale.get('Number.' + key); + }; + + var negative = value < 0, + decimal = getOption('decimal'), + precision = getOption('precision'), + group = getOption('group'), + decimals = getOption('decimals'); + + if (negative){ + var negativeLocale = getOption('negative') || {}; + if (negativeLocale.prefix == null && negativeLocale.suffix == null) negativeLocale.prefix = '-'; + ['prefix', 'suffix'].each(function(key){ + if (negativeLocale[key]) options[key] = getOption(key) + negativeLocale[key]; + }); + + value = -value; + } + + var prefix = getOption('prefix'), + suffix = getOption('suffix'); + + if (decimals !== '' && decimals >= 0 && decimals <= 20) value = value.toFixed(decimals); + if (precision >= 1 && precision <= 21) value = (+value).toPrecision(precision); + + value += ''; + var index; + if (getOption('scientific') === false && value.indexOf('e') > -1){ + var match = value.split('e'), + zeros = +match[1]; + value = match[0].replace('.', ''); + + if (zeros < 0){ + zeros = -zeros - 1; + index = match[0].indexOf('.'); + if (index > -1) zeros -= index - 1; + while (zeros--) value = '0' + value; + value = '0.' + value; + } else { + index = match[0].lastIndexOf('.'); + if (index > -1) zeros -= match[0].length - index - 1; + while (zeros--) value += '0'; + } + } + + if (decimal != '.') value = value.replace('.', decimal); + + if (group){ + index = value.lastIndexOf(decimal); + index = (index > -1) ? index : value.length; + var newOutput = value.substring(index), + i = index; + + while (i--){ + if ((index - i - 1) % 3 == 0 && i != (index - 1)) newOutput = group + newOutput; + newOutput = value.charAt(i) + newOutput; + } + + value = newOutput; + } + + if (prefix) value = prefix + value; + if (suffix) value += suffix; + + return value; + }, + + formatCurrency: function(){ + var locale = Locale.get('Number.currency') || {}; + if (locale.scientific == null) locale.scientific = false; + if (locale.decimals == null) locale.decimals = 2; + + return this.format(locale); + }, + + formatPercentage: function(){ + var locale = Locale.get('Number.percentage') || {}; + if (locale.suffix == null) locale.suffix = '%'; + if (locale.decimals == null) locale.decimals = 2; + + return this.format(locale); + } + +}); + + +/* +--- + +script: String.Extras.js + +name: String.Extras + +description: Extends the String native object to include methods useful in managing various kinds of strings (query strings, urls, html, etc). + +license: MIT-style license + +authors: + - Aaron Newton + - Guillermo Rauch + - Christopher Pitt + +requires: + - Core/String + - Core/Array + - MooTools.More + +provides: [String.Extras] + +... +*/ + +(function(){ + +var special = { + 'a': /[àáâãäåăą]/g, + 'A': /[ÀÃÂÃÄÅĂĄ]/g, + 'c': /[ćÄç]/g, + 'C': /[ĆČÇ]/g, + 'd': /[ÄÄ‘]/g, + 'D': /[ÄŽÃ]/g, + 'e': /[èéêëěę]/g, + 'E': /[ÈÉÊËĚĘ]/g, + 'g': /[ÄŸ]/g, + 'G': /[Äž]/g, + 'i': /[ìíîï]/g, + 'I': /[ÃŒÃÃŽÃ]/g, + 'l': /[ĺľł]/g, + 'L': /[ĹĽÅ]/g, + 'n': /[ñňń]/g, + 'N': /[ÑŇŃ]/g, + 'o': /[òóôõöøő]/g, + 'O': /[ÒÓÔÕÖØ]/g, + 'r': /[řŕ]/g, + 'R': /[ŘŔ]/g, + 's': /[Å¡Å¡ÅŸ]/g, + 'S': /[ŠŞŚ]/g, + 't': /[ťţ]/g, + 'T': /[ŤŢ]/g, + 'ue': /[ü]/g, + 'UE': /[Ãœ]/g, + 'u': /[ùúûůµ]/g, + 'U': /[ÙÚÛŮ]/g, + 'y': /[ÿý]/g, + 'Y': /[ŸÃ]/g, + 'z': /[žźż]/g, + 'Z': /[ŽŹŻ]/g, + 'th': /[þ]/g, + 'TH': /[Þ]/g, + 'dh': /[ð]/g, + 'DH': /[Ã]/g, + 'ss': /[ß]/g, + 'oe': /[Å“]/g, + 'OE': /[Å’]/g, + 'ae': /[æ]/g, + 'AE': /[Æ]/g +}, + +tidy = { + ' ': /[\xa0\u2002\u2003\u2009]/g, + '*': /[\xb7]/g, + '\'': /[\u2018\u2019]/g, + '"': /[\u201c\u201d]/g, + '...': /[\u2026]/g, + '-': /[\u2013]/g, +// '--': /[\u2014]/g, + '»': /[\uFFFD]/g +}; + +var walk = function(string, replacements){ + var result = string, key; + for (key in replacements) result = result.replace(replacements[key], key); + return result; +}; + +var getRegexForTag = function(tag, contents){ + tag = tag || ''; + var regstr = contents ? "<" + tag + "(?!\\w)[^>]*>([\\s\\S]*?)<\/" + tag + "(?!\\w)>" : "<\/?" + tag + "([^>]+)?>", + reg = new RegExp(regstr, "gi"); + return reg; +}; + +String.implement({ + + standardize: function(){ + return walk(this, special); + }, + + repeat: function(times){ + return new Array(times + 1).join(this); + }, + + pad: function(length, str, direction){ + if (this.length >= length) return this; + + var pad = (str == null ? ' ' : '' + str) + .repeat(length - this.length) + .substr(0, length - this.length); + + if (!direction || direction == 'right') return this + pad; + if (direction == 'left') return pad + this; + + return pad.substr(0, (pad.length / 2).floor()) + this + pad.substr(0, (pad.length / 2).ceil()); + }, + + getTags: function(tag, contents){ + return this.match(getRegexForTag(tag, contents)) || []; + }, + + stripTags: function(tag, contents){ + return this.replace(getRegexForTag(tag, contents), ''); + }, + + tidy: function(){ + return walk(this, tidy); + }, + + truncate: function(max, trail, atChar){ + var string = this; + if (trail == null && arguments.length == 1) trail = '…'; + if (string.length > max){ + string = string.substring(0, max); + if (atChar){ + var index = string.lastIndexOf(atChar); + if (index != -1) string = string.substr(0, index); + } + if (trail) string += trail; + } + return string; + } + +}); + +})(); + + +/* +--- + +script: String.QueryString.js + +name: String.QueryString + +description: Methods for dealing with URI query strings. + +license: MIT-style license + +authors: + - Sebastian MarkbÃ¥ge + - Aaron Newton + - Lennart Pilon + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - /MooTools.More + +provides: [String.QueryString] + +... +*/ + +String.implement({ + + parseQueryString: function(decodeKeys, decodeValues){ + if (decodeKeys == null) decodeKeys = true; + if (decodeValues == null) decodeValues = true; + + var vars = this.split(/[&;]/), + object = {}; + if (!vars.length) return object; + + vars.each(function(val){ + var index = val.indexOf('=') + 1, + value = index ? val.substr(index) : '', + keys = index ? val.substr(0, index - 1).match(/([^\]\[]+|(\B)(?=\]))/g) : [val], + obj = object; + if (!keys) return; + if (decodeValues) value = decodeURIComponent(value); + keys.each(function(key, i){ + if (decodeKeys) key = decodeURIComponent(key); + var current = obj[key]; + + if (i < keys.length - 1) obj = obj[key] = current || {}; + else if (typeOf(current) == 'array') current.push(value); + else obj[key] = current != null ? [current, value] : value; + }); + }); + + return object; + }, + + cleanQueryString: function(method){ + return this.split('&').filter(function(val){ + var index = val.indexOf('='), + key = index < 0 ? '' : val.substr(0, index), + value = val.substr(index + 1); + + return method ? method.call(null, key, value) : (value || value === 0); + }).join('&'); + } + +}); + + +/* +--- + +script: URI.js + +name: URI + +description: Provides methods useful in managing the window location and uris. + +license: MIT-style license + +authors: + - Sebastian MarkbÃ¥ge + - Aaron Newton + +requires: + - Core/Object + - Core/Class + - Core/Class.Extras + - Core/Element + - /String.QueryString + +provides: [URI] + +... +*/ + +(function(){ + +var toString = function(){ + return this.get('value'); +}; + +var URI = this.URI = new Class({ + + Implements: Options, + + options: { + /*base: false*/ + }, + + regex: /^(?:(\w+):)?(?:\/\/(?:(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?)?(\.\.?$|(?:[^?#\/]*\/)*)([^?#]*)(?:\?([^#]*))?(?:#(.*))?/, + parts: ['scheme', 'user', 'password', 'host', 'port', 'directory', 'file', 'query', 'fragment'], + schemes: {http: 80, https: 443, ftp: 21, rtsp: 554, mms: 1755, file: 0}, + + initialize: function(uri, options){ + this.setOptions(options); + var base = this.options.base || URI.base; + if (!uri) uri = base; + + if (uri && uri.parsed) this.parsed = Object.clone(uri.parsed); + else this.set('value', uri.href || uri.toString(), base ? new URI(base) : false); + }, + + parse: function(value, base){ + var bits = value.match(this.regex); + if (!bits) return false; + bits.shift(); + return this.merge(bits.associate(this.parts), base); + }, + + merge: function(bits, base){ + if ((!bits || !bits.scheme) && (!base || !base.scheme)) return false; + if (base){ + this.parts.every(function(part){ + if (bits[part]) return false; + bits[part] = base[part] || ''; + return true; + }); + } + bits.port = bits.port || this.schemes[bits.scheme.toLowerCase()]; + bits.directory = bits.directory ? this.parseDirectory(bits.directory, base ? base.directory : '') : '/'; + return bits; + }, + + parseDirectory: function(directory, baseDirectory){ + directory = (directory.substr(0, 1) == '/' ? '' : (baseDirectory || '/')) + directory; + if (!directory.test(URI.regs.directoryDot)) return directory; + var result = []; + directory.replace(URI.regs.endSlash, '').split('/').each(function(dir){ + if (dir == '..' && result.length > 0) result.pop(); + else if (dir != '.') result.push(dir); + }); + return result.join('/') + '/'; + }, + + combine: function(bits){ + return bits.value || bits.scheme + '://' + + (bits.user ? bits.user + (bits.password ? ':' + bits.password : '') + '@' : '') + + (bits.host || '') + (bits.port && bits.port != this.schemes[bits.scheme] ? ':' + bits.port : '') + + (bits.directory || '/') + (bits.file || '') + + (bits.query ? '?' + bits.query : '') + + (bits.fragment ? '#' + bits.fragment : ''); + }, + + set: function(part, value, base){ + if (part == 'value'){ + var scheme = value.match(URI.regs.scheme); + if (scheme) scheme = scheme[1]; + if (scheme && this.schemes[scheme.toLowerCase()] == null) this.parsed = { scheme: scheme, value: value }; + else this.parsed = this.parse(value, (base || this).parsed) || (scheme ? { scheme: scheme, value: value } : { value: value }); + } else if (part == 'data'){ + this.setData(value); + } else { + this.parsed[part] = value; + } + return this; + }, + + get: function(part, base){ + switch (part){ + case 'value': return this.combine(this.parsed, base ? base.parsed : false); + case 'data' : return this.getData(); + } + return this.parsed[part] || ''; + }, + + go: function(){ + document.location.href = this.toString(); + }, + + toURI: function(){ + return this; + }, + + getData: function(key, part){ + var qs = this.get(part || 'query'); + if (!(qs || qs === 0)) return key ? null : {}; + var obj = qs.parseQueryString(); + return key ? obj[key] : obj; + }, + + setData: function(values, merge, part){ + if (typeof values == 'string'){ + var data = this.getData(); + data[arguments[0]] = arguments[1]; + values = data; + } else if (merge){ + values = Object.merge(this.getData(), values); + } + return this.set(part || 'query', Object.toQueryString(values)); + }, + + clearData: function(part){ + return this.set(part || 'query', ''); + }, + + toString: toString, + valueOf: toString + +}); + +URI.regs = { + endSlash: /\/$/, + scheme: /^(\w+):/, + directoryDot: /\.\/|\.$/ +}; + +URI.base = new URI(Array.from(document.getElements('base[href]', true)).getLast(), {base: document.location}); + +String.implement({ + + toURI: function(options){ + return new URI(this, options); + } + +}); + +})(); + + +/* +--- + +script: Class.Refactor.js + +name: Class.Refactor + +description: Extends a class onto itself with new property, preserving any items attached to the class's namespace. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - /MooTools.More + +# Some modules declare themselves dependent on Class.Refactor +provides: [Class.refactor, Class.Refactor] + +... +*/ + +Class.refactor = function(original, refactors){ + + Object.each(refactors, function(item, name){ + var origin = original.prototype[name]; + origin = (origin && origin.$origin) || origin || function(){}; + original.implement(name, (typeof item == 'function') ? function(){ + var old = this.previous; + this.previous = origin; + var value = item.apply(this, arguments); + this.previous = old; + return value; + } : item); + }); + + return original; + +}; + + +/* +--- + +script: URI.Relative.js + +name: URI.Relative + +description: Extends the URI class to add methods for computing relative and absolute urls. + +license: MIT-style license + +authors: + - Sebastian MarkbÃ¥ge + + +requires: + - /Class.refactor + - /URI + +provides: [URI.Relative] + +... +*/ + +URI = Class.refactor(URI, { + + combine: function(bits, base){ + if (!base || bits.scheme != base.scheme || bits.host != base.host || bits.port != base.port) + return this.previous.apply(this, arguments); + var end = bits.file + (bits.query ? '?' + bits.query : '') + (bits.fragment ? '#' + bits.fragment : ''); + + if (!base.directory) return (bits.directory || (bits.file ? '' : './')) + end; + + var baseDir = base.directory.split('/'), + relDir = bits.directory.split('/'), + path = '', + offset; + + var i = 0; + for (offset = 0; offset < baseDir.length && offset < relDir.length && baseDir[offset] == relDir[offset]; offset++); + for (i = 0; i < baseDir.length - offset - 1; i++) path += '../'; + for (i = offset; i < relDir.length - 1; i++) path += relDir[i] + '/'; + + return (path || (bits.file ? '' : './')) + end; + }, + + toAbsolute: function(base){ + base = new URI(base); + if (base) base.set('directory', '').set('file', ''); + return this.toRelative(base); + }, + + toRelative: function(base){ + return this.get('value', new URI(base)); + } + +}); + + +/* +--- + +name: Hash + +description: Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects. + +license: MIT-style license. + +requires: + - Core/Object + - /MooTools.More + +provides: [Hash] + +... +*/ + +(function(){ + +if (this.Hash) return; + +var Hash = this.Hash = new Type('Hash', function(object){ + if (typeOf(object) == 'hash') object = Object.clone(object.getClean()); + for (var key in object) this[key] = object[key]; + return this; +}); + +this.$H = function(object){ + return new Hash(object); +}; + +Hash.implement({ + + forEach: function(fn, bind){ + Object.forEach(this, fn, bind); + }, + + getClean: function(){ + var clean = {}; + for (var key in this){ + if (this.hasOwnProperty(key)) clean[key] = this[key]; + } + return clean; + }, + + getLength: function(){ + var length = 0; + for (var key in this){ + if (this.hasOwnProperty(key)) length++; + } + return length; + } + +}); + +Hash.alias('each', 'forEach'); + +Hash.implement({ + + has: Object.prototype.hasOwnProperty, + + keyOf: function(value){ + return Object.keyOf(this, value); + }, + + hasValue: function(value){ + return Object.contains(this, value); + }, + + extend: function(properties){ + Hash.each(properties || {}, function(value, key){ + Hash.set(this, key, value); + }, this); + return this; + }, + + combine: function(properties){ + Hash.each(properties || {}, function(value, key){ + Hash.include(this, key, value); + }, this); + return this; + }, + + erase: function(key){ + if (this.hasOwnProperty(key)) delete this[key]; + return this; + }, + + get: function(key){ + return (this.hasOwnProperty(key)) ? this[key] : null; + }, + + set: function(key, value){ + if (!this[key] || this.hasOwnProperty(key)) this[key] = value; + return this; + }, + + empty: function(){ + Hash.each(this, function(value, key){ + delete this[key]; + }, this); + return this; + }, + + include: function(key, value){ + if (this[key] == undefined) this[key] = value; + return this; + }, + + map: function(fn, bind){ + return new Hash(Object.map(this, fn, bind)); + }, + + filter: function(fn, bind){ + return new Hash(Object.filter(this, fn, bind)); + }, + + every: function(fn, bind){ + return Object.every(this, fn, bind); + }, + + some: function(fn, bind){ + return Object.some(this, fn, bind); + }, + + getKeys: function(){ + return Object.keys(this); + }, + + getValues: function(){ + return Object.values(this); + }, + + toQueryString: function(base){ + return Object.toQueryString(this, base); + } + +}); + +Hash.alias({indexOf: 'keyOf', contains: 'hasValue'}); + + +})(); + + + +/* +--- + +script: Hash.Extras.js + +name: Hash.Extras + +description: Extends the Hash Type to include getFromPath which allows a path notation to child elements. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Hash + - /Object.Extras + +provides: [Hash.Extras] + +... +*/ + +Hash.implement({ + + getFromPath: function(notation){ + return Object.getFromPath(this, notation); + }, + + cleanValues: function(method){ + return new Hash(Object.cleanValues(this, method)); + }, + + run: function(){ + Object.run(arguments); + } + +}); + + +/* +--- + +script: Element.Forms.js + +name: Element.Forms + +description: Extends the Element native object to include methods useful in managing inputs. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element + - /String.Extras + - /MooTools.More + +provides: [Element.Forms] + +... +*/ + +Element.implement({ + + tidy: function(){ + this.set('value', this.get('value').tidy()); + }, + + getTextInRange: function(start, end){ + return this.get('value').substring(start, end); + }, + + getSelectedText: function(){ + if (this.setSelectionRange) return this.getTextInRange(this.getSelectionStart(), this.getSelectionEnd()); + return document.selection.createRange().text; + }, + + getSelectedRange: function(){ + if (this.selectionStart != null){ + return { + start: this.selectionStart, + end: this.selectionEnd + }; + } + + var pos = { + start: 0, + end: 0 + }; + var range = this.getDocument().selection.createRange(); + if (!range || range.parentElement() != this) return pos; + var duplicate = range.duplicate(); + + if (this.type == 'text'){ + pos.start = 0 - duplicate.moveStart('character', -100000); + pos.end = pos.start + range.text.length; + } else { + var value = this.get('value'); + var offset = value.length; + duplicate.moveToElementText(this); + duplicate.setEndPoint('StartToEnd', range); + if (duplicate.text.length) offset -= value.match(/[\n\r]*$/)[0].length; + pos.end = offset - duplicate.text.length; + duplicate.setEndPoint('StartToStart', range); + pos.start = offset - duplicate.text.length; + } + return pos; + }, + + getSelectionStart: function(){ + return this.getSelectedRange().start; + }, + + getSelectionEnd: function(){ + return this.getSelectedRange().end; + }, + + setCaretPosition: function(pos){ + if (pos == 'end') pos = this.get('value').length; + this.selectRange(pos, pos); + return this; + }, + + getCaretPosition: function(){ + return this.getSelectedRange().start; + }, + + selectRange: function(start, end){ + if (this.setSelectionRange){ + this.focus(); + this.setSelectionRange(start, end); + } else { + var value = this.get('value'); + var diff = value.substr(start, end - start).replace(/\r/g, '').length; + start = value.substr(0, start).replace(/\r/g, '').length; + var range = this.createTextRange(); + range.collapse(true); + range.moveEnd('character', start + diff); + range.moveStart('character', start); + range.select(); + } + return this; + }, + + insertAtCursor: function(value, select){ + var pos = this.getSelectedRange(); + var text = this.get('value'); + this.set('value', text.substring(0, pos.start) + value + text.substring(pos.end, text.length)); + if (select !== false) this.selectRange(pos.start, pos.start + value.length); + else this.setCaretPosition(pos.start + value.length); + return this; + }, + + insertAroundCursor: function(options, select){ + options = Object.append({ + before: '', + defaultMiddle: '', + after: '' + }, options); + + var value = this.getSelectedText() || options.defaultMiddle; + var pos = this.getSelectedRange(); + var text = this.get('value'); + + if (pos.start == pos.end){ + this.set('value', text.substring(0, pos.start) + options.before + value + options.after + text.substring(pos.end, text.length)); + this.selectRange(pos.start + options.before.length, pos.end + options.before.length + value.length); + } else { + var current = text.substring(pos.start, pos.end); + this.set('value', text.substring(0, pos.start) + options.before + current + options.after + text.substring(pos.end, text.length)); + var selStart = pos.start + options.before.length; + if (select !== false) this.selectRange(selStart, selStart + current.length); + else this.setCaretPosition(selStart + text.length); + } + return this; + } + +}); + + +/* +--- + +script: Elements.From.js + +name: Elements.From + +description: Returns a collection of elements from a string of html. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/String + - Core/Element + - /MooTools.More + +provides: [Elements.from, Elements.From] + +... +*/ + +Elements.from = function(text, excludeScripts){ + if (excludeScripts || excludeScripts == null) text = text.stripScripts(); + + var container, match = text.match(/^\s*<(t[dhr]|tbody|tfoot|thead)/i); + + if (match){ + container = new Element('table'); + var tag = match[1].toLowerCase(); + if (['td', 'th', 'tr'].contains(tag)){ + container = new Element('tbody').inject(container); + if (tag != 'tr') container = new Element('tr').inject(container); + } + } + + return (container || new Element('div')).set('html', text).getChildren(); +}; + + +/* +--- + +name: Events.Pseudos + +description: Adds the functionality to add pseudo events + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Class.Extras, Core/Slick.Parser, More/MooTools.More] + +provides: [Events.Pseudos] + +... +*/ + +Events.Pseudos = function(pseudos, addEvent, removeEvent){ + + var storeKey = 'monitorEvents:'; + + var storageOf = function(object){ + return { + store: object.store ? function(key, value){ + object.store(storeKey + key, value); + } : function(key, value){ + (object.$monitorEvents || (object.$monitorEvents = {}))[key] = value; + }, + retrieve: object.retrieve ? function(key, dflt){ + return object.retrieve(storeKey + key, dflt); + } : function(key, dflt){ + if (!object.$monitorEvents) return dflt; + return object.$monitorEvents[key] || dflt; + } + }; + }; + + var splitType = function(type){ + if (type.indexOf(':') == -1 || !pseudos) return null; + + var parsed = Slick.parse(type).expressions[0][0], + parsedPseudos = parsed.pseudos, + l = parsedPseudos.length, + splits = []; + + while (l--) if (pseudos[parsedPseudos[l].key]){ + splits.push({ + event: parsed.tag, + value: parsedPseudos[l].value, + pseudo: parsedPseudos[l].key, + original: type + }); + } + + return splits.length ? splits : null; + }; + + var mergePseudoOptions = function(split){ + return Object.merge.apply(this, split.map(function(item){ + return pseudos[item.pseudo].options || {}; + })); + }; + + return { + + addEvent: function(type, fn, internal){ + var split = splitType(type); + if (!split) return addEvent.call(this, type, fn, internal); + + var storage = storageOf(this), + events = storage.retrieve(type, []), + eventType = split[0].event, + options = mergePseudoOptions(split), + stack = fn, + eventOptions = options[eventType] || {}, + args = Array.slice(arguments, 2), + self = this, + monitor; + + if (eventOptions.args) args.append(Array.from(eventOptions.args)); + if (eventOptions.base) eventType = eventOptions.base; + if (eventOptions.onAdd) eventOptions.onAdd(this); + + split.each(function(item){ + var stackFn = stack; + stack = function(){ + (eventOptions.listener || pseudos[item.pseudo].listener).call(self, item, stackFn, arguments, monitor, options); + }; + }); + monitor = stack.bind(this); + + events.include({event: fn, monitor: monitor}); + storage.store(type, events); + + addEvent.apply(this, [type, fn].concat(args)); + return addEvent.apply(this, [eventType, monitor].concat(args)); + }, + + removeEvent: function(type, fn){ + var split = splitType(type); + if (!split) return removeEvent.call(this, type, fn); + + var storage = storageOf(this), + events = storage.retrieve(type); + if (!events) return this; + + var eventType = split[0].event, + options = mergePseudoOptions(split), + eventOptions = options[eventType] || {}, + args = Array.slice(arguments, 2); + + if (eventOptions.args) args.append(Array.from(eventOptions.args)); + if (eventOptions.base) eventType = eventOptions.base; + if (eventOptions.onRemove) eventOptions.onRemove(this); + + removeEvent.apply(this, [type, fn].concat(args)); + events.each(function(monitor, i){ + if (!fn || monitor.event == fn) removeEvent.apply(this, [eventType, monitor.monitor].concat(args)); + delete events[i]; + }, this); + + storage.store(type, events); + return this; + } + + }; + +}; + +(function(){ + +var pseudos = { + + once: { + listener: function(split, fn, args, monitor){ + fn.apply(this, args); + this.removeEvent(split.event, monitor) + .removeEvent(split.original, fn); + } + }, + + throttle: { + listener: function(split, fn, args){ + if (!fn._throttled){ + fn.apply(this, args); + fn._throttled = setTimeout(function(){ + fn._throttled = false; + }, split.value || 250); + } + } + }, + + pause: { + listener: function(split, fn, args){ + clearTimeout(fn._pause); + fn._pause = fn.delay(split.value || 250, this, args); + } + } + +}; + +Events.definePseudo = function(key, listener){ + pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener; + return this; +}; + +Events.lookupPseudo = function(key){ + return pseudos[key]; +}; + +var proto = Events.prototype; +Events.implement(Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +['Request', 'Fx'].each(function(klass){ + if (this[klass]) this[klass].implement(Events.prototype); +}); + +})(); + + +/* +--- + +name: Element.Event.Pseudos + +description: Adds the functionality to add pseudo events for Elements + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Core/Element.Event, Events.Pseudos] + +provides: [Element.Event.Pseudos] + +... +*/ + +(function(){ + +var pseudos = {}, + copyFromEvents = ['once', 'throttle', 'pause'], + count = copyFromEvents.length; + +while (count--) pseudos[copyFromEvents[count]] = Events.lookupPseudo(copyFromEvents[count]); + +Event.definePseudo = function(key, listener){ + pseudos[key] = Type.isFunction(listener) ? {listener: listener} : listener; + return this; +}; + +var proto = Element.prototype; +[Element, Window, Document].invoke('implement', Events.Pseudos(pseudos, proto.addEvent, proto.removeEvent)); + +})(); + + +/* +--- + +name: Element.Event.Pseudos.Keys + +description: Adds functionality fire events if certain keycombinations are pressed + +license: MIT-style license + +authors: + - Arian Stolwijk + +requires: [Element.Event.Pseudos] + +provides: [Element.Event.Pseudos.Keys] + +... +*/ + +(function(){ + +var keysStoreKey = '$moo:keys-pressed', + keysKeyupStoreKey = '$moo:keys-keyup'; + + +Event.definePseudo('keys', function(split, fn, args){ + + var event = args[0], + keys = [], + pressed = this.retrieve(keysStoreKey, []); + + keys.append(split.value.replace('++', function(){ + keys.push('+'); // shift++ and shift+++a + return ''; + }).split('+')); + + pressed.include(event.key); + + if (keys.every(function(key){ + return pressed.contains(key); + })) fn.apply(this, args); + + this.store(keysStoreKey, pressed); + + if (!this.retrieve(keysKeyupStoreKey)){ + var keyup = function(event){ + (function(){ + pressed = this.retrieve(keysStoreKey, []).erase(event.key); + this.store(keysStoreKey, pressed); + }).delay(0, this); // Fix for IE + }; + this.store(keysKeyupStoreKey, keyup).addEvent('keyup', keyup); + } + +}); + +Object.append(Event.Keys, { + 'shift': 16, + 'control': 17, + 'alt': 18, + 'capslock': 20, + 'pageup': 33, + 'pagedown': 34, + 'end': 35, + 'home': 36, + 'numlock': 144, + 'scrolllock': 145, + ';': 186, + '=': 187, + ',': 188, + '-': Browser.firefox ? 109 : 189, + '.': 190, + '/': 191, + '`': 192, + '[': 219, + '\\': 220, + ']': 221, + "'": 222, + '+': 107 +}); + +})(); + + +/* +--- + +script: Element.Pin.js + +name: Element.Pin + +description: Extends the Element native object to include the pin method useful for fixed positioning for elements. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Event + - Core/Element.Dimensions + - Core/Element.Style + - /MooTools.More + +provides: [Element.Pin] + +... +*/ + +(function(){ + var supportsPositionFixed = false, + supportTested = false; + + var testPositionFixed = function(){ + var test = new Element('div').setStyles({ + position: 'fixed', + top: 0, + right: 0 + }).inject(document.body); + supportsPositionFixed = (test.offsetTop === 0); + test.dispose(); + supportTested = true; + }; + + Element.implement({ + + pin: function(enable, forceScroll){ + if (!supportTested) testPositionFixed(); + if (this.getStyle('display') == 'none') return this; + + var pinnedPosition, + scroll = window.getScroll(), + parent, + scrollFixer; + + if (enable !== false){ + pinnedPosition = this.getPosition(supportsPositionFixed ? document.body : this.getOffsetParent()); + if (!this.retrieve('pin:_pinned')){ + var currentPosition = { + top: pinnedPosition.y - scroll.y, + left: pinnedPosition.x - scroll.x + }; + + if (supportsPositionFixed && !forceScroll){ + this.setStyle('position', 'fixed').setStyles(currentPosition); + } else { + + parent = this.getOffsetParent(); + var position = this.getPosition(parent), + styles = this.getStyles('left', 'top'); + + if (parent && styles.left == 'auto' || styles.top == 'auto') this.setPosition(position); + if (this.getStyle('position') == 'static') this.setStyle('position', 'absolute'); + + position = { + x: styles.left.toInt() - scroll.x, + y: styles.top.toInt() - scroll.y + }; + + scrollFixer = function(){ + if (!this.retrieve('pin:_pinned')) return; + var scroll = window.getScroll(); + this.setStyles({ + left: position.x + scroll.x, + top: position.y + scroll.y + }); + }.bind(this); + + this.store('pin:_scrollFixer', scrollFixer); + window.addEvent('scroll', scrollFixer); + } + this.store('pin:_pinned', true); + } + + } else { + if (!this.retrieve('pin:_pinned')) return this; + + parent = this.getParent(); + var offsetParent = (parent.getComputedStyle('position') != 'static' ? parent : parent.getOffsetParent()); + + pinnedPosition = this.getPosition(offsetParent); + + this.store('pin:_pinned', false); + scrollFixer = this.retrieve('pin:_scrollFixer'); + if (!scrollFixer){ + this.setStyles({ + position: 'absolute', + top: pinnedPosition.y + scroll.y, + left: pinnedPosition.x + scroll.x + }); + } else { + this.store('pin:_scrollFixer', null); + window.removeEvent('scroll', scrollFixer); + } + this.removeClass('isPinned'); + } + return this; + }, + + unpin: function(){ + return this.pin(false); + }, + + togglePin: function(){ + return this.pin(!this.retrieve('pin:_pinned')); + } + + }); + + + +})(); + + +/* +--- + +script: Element.Measure.js + +name: Element.Measure + +description: Extends the Element native object to include methods useful in measuring dimensions. + +credits: "Element.measure / .expose methods by Daniel Steigerwald License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz" + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - Core/Element.Dimensions + - /MooTools.More + +provides: [Element.Measure] + +... +*/ + +(function(){ + +var getStylesList = function(styles, planes){ + var list = []; + Object.each(planes, function(directions){ + Object.each(directions, function(edge){ + styles.each(function(style){ + list.push(style + '-' + edge + (style == 'border' ? '-width' : '')); + }); + }); + }); + return list; +}; + +var calculateEdgeSize = function(edge, styles){ + var total = 0; + Object.each(styles, function(value, style){ + if (style.test(edge)) total = total + value.toInt(); + }); + return total; +}; + +var isVisible = function(el){ + return !!(!el || el.offsetHeight || el.offsetWidth); +}; + + +Element.implement({ + + measure: function(fn){ + if (isVisible(this)) return fn.call(this); + var parent = this.getParent(), + toMeasure = []; + while (!isVisible(parent) && parent != document.body){ + toMeasure.push(parent.expose()); + parent = parent.getParent(); + } + var restore = this.expose(), + result = fn.call(this); + restore(); + toMeasure.each(function(restore){ + restore(); + }); + return result; + }, + + expose: function(){ + if (this.getStyle('display') != 'none') return function(){}; + var before = this.style.cssText; + this.setStyles({ + display: 'block', + position: 'absolute', + visibility: 'hidden' + }); + return function(){ + this.style.cssText = before; + }.bind(this); + }, + + getDimensions: function(options){ + options = Object.merge({computeSize: false}, options); + var dim = {x: 0, y: 0}; + + var getSize = function(el, options){ + return (options.computeSize) ? el.getComputedSize(options) : el.getSize(); + }; + + var parent = this.getParent('body'); + + if (parent && this.getStyle('display') == 'none'){ + dim = this.measure(function(){ + return getSize(this, options); + }); + } else if (parent){ + try { //safari sometimes crashes here, so catch it + dim = getSize(this, options); + }catch(e){} + } + + return Object.append(dim, (dim.x || dim.x === 0) ? { + width: dim.x, + height: dim.y + } : { + x: dim.width, + y: dim.height + } + ); + }, + + getComputedSize: function(options){ + + + options = Object.merge({ + styles: ['padding','border'], + planes: { + height: ['top','bottom'], + width: ['left','right'] + }, + mode: 'both' + }, options); + + var styles = {}, + size = {width: 0, height: 0}, + dimensions; + + if (options.mode == 'vertical'){ + delete size.width; + delete options.planes.width; + } else if (options.mode == 'horizontal'){ + delete size.height; + delete options.planes.height; + } + + getStylesList(options.styles, options.planes).each(function(style){ + styles[style] = this.getStyle(style).toInt(); + }, this); + + Object.each(options.planes, function(edges, plane){ + + var capitalized = plane.capitalize(), + style = this.getStyle(plane); + + if (style == 'auto' && !dimensions) dimensions = this.getDimensions(); + + style = styles[plane] = (style == 'auto') ? dimensions[plane] : style.toInt(); + size['total' + capitalized] = style; + + edges.each(function(edge){ + var edgesize = calculateEdgeSize(edge, styles); + size['computed' + edge.capitalize()] = edgesize; + size['total' + capitalized] += edgesize; + }); + + }, this); + + return Object.append(size, styles); + } + +}); + +})(); + + +/* +--- + +script: Element.Position.js + +name: Element.Position + +description: Extends the Element native object to include methods useful positioning elements relative to others. + +license: MIT-style license + +authors: + - Aaron Newton + - Jacob Thornton + +requires: + - Core/Options + - Core/Element.Dimensions + - Element.Measure + +provides: [Element.Position] + +... +*/ + +(function(original){ + +var local = Element.Position = { + + options: {/* + edge: false, + returnPos: false, + minimum: {x: 0, y: 0}, + maximum: {x: 0, y: 0}, + relFixedPosition: false, + ignoreMargins: false, + ignoreScroll: false, + allowNegative: false,*/ + relativeTo: document.body, + position: { + x: 'center', //left, center, right + y: 'center' //top, center, bottom + }, + offset: {x: 0, y: 0} + }, + + getOptions: function(element, options){ + options = Object.merge({}, local.options, options); + local.setPositionOption(options); + local.setEdgeOption(options); + local.setOffsetOption(element, options); + local.setDimensionsOption(element, options); + return options; + }, + + setPositionOption: function(options){ + options.position = local.getCoordinateFromValue(options.position); + }, + + setEdgeOption: function(options){ + var edgeOption = local.getCoordinateFromValue(options.edge); + options.edge = edgeOption ? edgeOption : + (options.position.x == 'center' && options.position.y == 'center') ? {x: 'center', y: 'center'} : + {x: 'left', y: 'top'}; + }, + + setOffsetOption: function(element, options){ + var parentOffset = {x: 0, y: 0}, + offsetParent = element.measure(function(){ + return document.id(this.getOffsetParent()); + }), + parentScroll = offsetParent.getScroll(); + + if (!offsetParent || offsetParent == element.getDocument().body) return; + parentOffset = offsetParent.measure(function(){ + var position = this.getPosition(); + if (this.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.x += scroll.x; + position.y += scroll.y; + } + return position; + }); + + options.offset = { + parentPositioned: offsetParent != document.id(options.relativeTo), + x: options.offset.x - parentOffset.x + parentScroll.x, + y: options.offset.y - parentOffset.y + parentScroll.y + }; + }, + + setDimensionsOption: function(element, options){ + options.dimensions = element.getDimensions({ + computeSize: true, + styles: ['padding', 'border', 'margin'] + }); + }, + + getPosition: function(element, options){ + var position = {}; + options = local.getOptions(element, options); + var relativeTo = document.id(options.relativeTo) || document.body; + + local.setPositionCoordinates(options, position, relativeTo); + if (options.edge) local.toEdge(position, options); + + var offset = options.offset; + position.left = ((position.x >= 0 || offset.parentPositioned || options.allowNegative) ? position.x : 0).toInt(); + position.top = ((position.y >= 0 || offset.parentPositioned || options.allowNegative) ? position.y : 0).toInt(); + + local.toMinMax(position, options); + + if (options.relFixedPosition || relativeTo.getStyle('position') == 'fixed') local.toRelFixedPosition(relativeTo, position); + if (options.ignoreScroll) local.toIgnoreScroll(relativeTo, position); + if (options.ignoreMargins) local.toIgnoreMargins(position, options); + + position.left = Math.ceil(position.left); + position.top = Math.ceil(position.top); + delete position.x; + delete position.y; + + return position; + }, + + setPositionCoordinates: function(options, position, relativeTo){ + var offsetY = options.offset.y, + offsetX = options.offset.x, + calc = (relativeTo == document.body) ? window.getScroll() : relativeTo.getPosition(), + top = calc.y, + left = calc.x, + winSize = window.getSize(); + + switch(options.position.x){ + case 'left': position.x = left + offsetX; break; + case 'right': position.x = left + offsetX + relativeTo.offsetWidth; break; + default: position.x = left + ((relativeTo == document.body ? winSize.x : relativeTo.offsetWidth) / 2) + offsetX; break; + } + + switch(options.position.y){ + case 'top': position.y = top + offsetY; break; + case 'bottom': position.y = top + offsetY + relativeTo.offsetHeight; break; + default: position.y = top + ((relativeTo == document.body ? winSize.y : relativeTo.offsetHeight) / 2) + offsetY; break; + } + }, + + toMinMax: function(position, options){ + var xy = {left: 'x', top: 'y'}, value; + ['minimum', 'maximum'].each(function(minmax){ + ['left', 'top'].each(function(lr){ + value = options[minmax] ? options[minmax][xy[lr]] : null; + if (value != null && ((minmax == 'minimum') ? position[lr] < value : position[lr] > value)) position[lr] = value; + }); + }); + }, + + toRelFixedPosition: function(relativeTo, position){ + var winScroll = window.getScroll(); + position.top += winScroll.y; + position.left += winScroll.x; + }, + + toIgnoreScroll: function(relativeTo, position){ + var relScroll = relativeTo.getScroll(); + position.top -= relScroll.y; + position.left -= relScroll.x; + }, + + toIgnoreMargins: function(position, options){ + position.left += options.edge.x == 'right' + ? options.dimensions['margin-right'] + : (options.edge.x != 'center' + ? -options.dimensions['margin-left'] + : -options.dimensions['margin-left'] + ((options.dimensions['margin-right'] + options.dimensions['margin-left']) / 2)); + + position.top += options.edge.y == 'bottom' + ? options.dimensions['margin-bottom'] + : (options.edge.y != 'center' + ? -options.dimensions['margin-top'] + : -options.dimensions['margin-top'] + ((options.dimensions['margin-bottom'] + options.dimensions['margin-top']) / 2)); + }, + + toEdge: function(position, options){ + var edgeOffset = {}, + dimensions = options.dimensions, + edge = options.edge; + + switch(edge.x){ + case 'left': edgeOffset.x = 0; break; + case 'right': edgeOffset.x = -dimensions.x - dimensions.computedRight - dimensions.computedLeft; break; + // center + default: edgeOffset.x = -(Math.round(dimensions.totalWidth / 2)); break; + } + + switch(edge.y){ + case 'top': edgeOffset.y = 0; break; + case 'bottom': edgeOffset.y = -dimensions.y - dimensions.computedTop - dimensions.computedBottom; break; + // center + default: edgeOffset.y = -(Math.round(dimensions.totalHeight / 2)); break; + } + + position.x += edgeOffset.x; + position.y += edgeOffset.y; + }, + + getCoordinateFromValue: function(option){ + if (typeOf(option) != 'string') return option; + option = option.toLowerCase(); + + return { + x: option.test('left') ? 'left' + : (option.test('right') ? 'right' : 'center'), + y: option.test(/upper|top/) ? 'top' + : (option.test('bottom') ? 'bottom' : 'center') + }; + } + +}; + +Element.implement({ + + position: function(options){ + if (options && (options.x != null || options.y != null)) { + return (original ? original.apply(this, arguments) : this); + } + var position = this.setStyle('position', 'absolute').calculatePosition(options); + return (options && options.returnPos) ? position : this.setStyles(position); + }, + + calculatePosition: function(options){ + return local.getPosition(this, options); + } + +}); + +})(Element.prototype.position); + + +/* +--- + +script: Element.Shortcuts.js + +name: Element.Shortcuts + +description: Extends the Element native object to include some shortcut methods. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Style + - /MooTools.More + +provides: [Element.Shortcuts] + +... +*/ + +Element.implement({ + + isDisplayed: function(){ + return this.getStyle('display') != 'none'; + }, + + isVisible: function(){ + var w = this.offsetWidth, + h = this.offsetHeight; + return (w == 0 && h == 0) ? false : (w > 0 && h > 0) ? true : this.style.display != 'none'; + }, + + toggle: function(){ + return this[this.isDisplayed() ? 'hide' : 'show'](); + }, + + hide: function(){ + var d; + try { + //IE fails here if the element is not in the dom + d = this.getStyle('display'); + } catch(e){} + if (d == 'none') return this; + return this.store('element:_originalDisplay', d || '').setStyle('display', 'none'); + }, + + show: function(display){ + if (!display && this.isDisplayed()) return this; + display = display || this.retrieve('element:_originalDisplay') || 'block'; + return this.setStyle('display', (display == 'none') ? 'block' : display); + }, + + swapClass: function(remove, add){ + return this.removeClass(remove).addClass(add); + } + +}); + +Document.implement({ + + clearSelection: function(){ + if (window.getSelection){ + var selection = window.getSelection(); + if (selection && selection.removeAllRanges) selection.removeAllRanges(); + } else if (document.selection && document.selection.empty){ + try { + //IE fails here if selected element is not in dom + document.selection.empty(); + } catch(e){} + } + } + +}); + + +/* +--- + +script: Class.Binds.js + +name: Class.Binds + +description: Automagically binds specified methods in a class to the instance of the class. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Class + - /MooTools.More + +provides: [Class.Binds] + +... +*/ + +Class.Mutators.Binds = function(binds){ + if (!this.prototype.initialize) this.implement('initialize', function(){}); + return Array.from(binds).concat(this.prototype.Binds || []); +}; + +Class.Mutators.initialize = function(initialize){ + return function(){ + Array.from(this.Binds).each(function(name){ + var original = this[name]; + if (original) this[name] = original.bind(this); + }, this); + return initialize.apply(this, arguments); + }; +}; + + +/* +--- + +script: Class.Occlude.js + +name: Class.Occlude + +description: Prevents a class from being applied to a DOM element twice. + +license: MIT-style license. + +authors: + - Aaron Newton + +requires: + - Core/Class + - Core/Element + - /MooTools.More + +provides: [Class.Occlude] + +... +*/ + +Class.Occlude = new Class({ + + occlude: function(property, element){ + element = document.id(element || this.element); + var instance = element.retrieve(property || this.property); + if (instance && !this.occluded) + return (this.occluded = instance); + + this.occluded = false; + element.store(property || this.property, this); + return this.occluded; + } + +}); + + +/* +--- + +script: IframeShim.js + +name: IframeShim + +description: Defines IframeShim, a class for obscuring select lists and flash objects in IE. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Event + - Core/Element.Style + - Core/Options + - Core/Events + - /Element.Position + - /Class.Occlude + +provides: [IframeShim] + +... +*/ + +var IframeShim = new Class({ + + Implements: [Options, Events, Class.Occlude], + + options: { + className: 'iframeShim', + src: 'javascript:false;document.write("");', + display: false, + zIndex: null, + margin: 0, + offset: {x: 0, y: 0}, + browsers: (Browser.ie6 || (Browser.firefox && Browser.version < 3 && Browser.Platform.mac)) + }, + + property: 'IframeShim', + + initialize: function(element, options){ + this.element = document.id(element); + if (this.occlude()) return this.occluded; + this.setOptions(options); + this.makeShim(); + return this; + }, + + makeShim: function(){ + if (this.options.browsers){ + var zIndex = this.element.getStyle('zIndex').toInt(); + + if (!zIndex){ + zIndex = 1; + var pos = this.element.getStyle('position'); + if (pos == 'static' || !pos) this.element.setStyle('position', 'relative'); + this.element.setStyle('zIndex', zIndex); + } + zIndex = ((this.options.zIndex != null || this.options.zIndex === 0) && zIndex > this.options.zIndex) ? this.options.zIndex : zIndex - 1; + if (zIndex < 0) zIndex = 1; + this.shim = new Element('iframe', { + src: this.options.src, + scrolling: 'no', + frameborder: 0, + styles: { + zIndex: zIndex, + position: 'absolute', + border: 'none', + filter: 'progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)' + }, + 'class': this.options.className + }).store('IframeShim', this); + var inject = (function(){ + this.shim.inject(this.element, 'after'); + this[this.options.display ? 'show' : 'hide'](); + this.fireEvent('inject'); + }).bind(this); + if (!IframeShim.ready) window.addEvent('load', inject); + else inject(); + } else { + this.position = this.hide = this.show = this.dispose = Function.from(this); + } + }, + + position: function(){ + if (!IframeShim.ready || !this.shim) return this; + var size = this.element.measure(function(){ + return this.getSize(); + }); + if (this.options.margin != undefined){ + size.x = size.x - (this.options.margin * 2); + size.y = size.y - (this.options.margin * 2); + this.options.offset.x += this.options.margin; + this.options.offset.y += this.options.margin; + } + this.shim.set({width: size.x, height: size.y}).position({ + relativeTo: this.element, + offset: this.options.offset + }); + return this; + }, + + hide: function(){ + if (this.shim) this.shim.setStyle('display', 'none'); + return this; + }, + + show: function(){ + if (this.shim) this.shim.setStyle('display', 'block'); + return this.position(); + }, + + dispose: function(){ + if (this.shim) this.shim.dispose(); + return this; + }, + + destroy: function(){ + if (this.shim) this.shim.destroy(); + return this; + } + +}); + +window.addEvent('load', function(){ + IframeShim.ready = true; +}); + + +/* +--- + +script: Mask.js + +name: Mask + +description: Creates a mask element to cover another. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - /Class.Binds + - /Element.Position + - /IframeShim + +provides: [Mask] + +... +*/ + +var Mask = new Class({ + + Implements: [Options, Events], + + Binds: ['position'], + + options: {/* + onShow: function(){}, + onHide: function(){}, + onDestroy: function(){}, + onClick: function(event){}, + inject: { + where: 'after', + target: null, + }, + hideOnClick: false, + id: null, + destroyOnHide: false,*/ + style: {}, + 'class': 'mask', + maskMargins: false, + useIframeShim: true, + iframeShimOptions: {} + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('mask', this); + this.setOptions(options); + this.render(); + this.inject(); + }, + + render: function(){ + this.element = new Element('div', { + 'class': this.options['class'], + id: this.options.id || 'mask-' + String.uniqueID(), + styles: Object.merge({}, this.options.style, { + display: 'none' + }), + events: { + click: function(event){ + this.fireEvent('click', event); + if (this.options.hideOnClick) this.hide(); + }.bind(this) + } + }); + + this.hidden = true; + }, + + toElement: function(){ + return this.element; + }, + + inject: function(target, where){ + where = where || (this.options.inject ? this.options.inject.where : '') || this.target == document.body ? 'inside' : 'after'; + target = target || (this.options.inject && this.options.inject.target) || this.target; + + this.element.inject(target, where); + + if (this.options.useIframeShim){ + this.shim = new IframeShim(this.element, this.options.iframeShimOptions); + + this.addEvents({ + show: this.shim.show.bind(this.shim), + hide: this.shim.hide.bind(this.shim), + destroy: this.shim.destroy.bind(this.shim) + }); + } + }, + + position: function(){ + this.resize(this.options.width, this.options.height); + + this.element.position({ + relativeTo: this.target, + position: 'topLeft', + ignoreMargins: !this.options.maskMargins, + ignoreScroll: this.target == document.body + }); + + return this; + }, + + resize: function(x, y){ + var opt = { + styles: ['padding', 'border'] + }; + if (this.options.maskMargins) opt.styles.push('margin'); + + var dim = this.target.getComputedSize(opt); + if (this.target == document.body){ + this.element.setStyles({width: 0, height: 0}); + var win = window.getScrollSize(); + if (dim.totalHeight < win.y) dim.totalHeight = win.y; + if (dim.totalWidth < win.x) dim.totalWidth = win.x; + } + this.element.setStyles({ + width: Array.pick([x, dim.totalWidth, dim.x]), + height: Array.pick([y, dim.totalHeight, dim.y]) + }); + + return this; + }, + + show: function(){ + if (!this.hidden) return this; + + window.addEvent('resize', this.position); + this.position(); + this.showMask.apply(this, arguments); + + return this; + }, + + showMask: function(){ + this.element.setStyle('display', 'block'); + this.hidden = false; + this.fireEvent('show'); + }, + + hide: function(){ + if (this.hidden) return this; + + window.removeEvent('resize', this.position); + this.hideMask.apply(this, arguments); + if (this.options.destroyOnHide) return this.destroy(); + + return this; + }, + + hideMask: function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + }, + + toggle: function(){ + this[this.hidden ? 'show' : 'hide'](); + }, + + destroy: function(){ + this.hide(); + this.element.destroy(); + this.fireEvent('destroy'); + this.target.eliminate('mask'); + } + +}); + +Element.Properties.mask = { + + set: function(options){ + var mask = this.retrieve('mask'); + if (mask) mask.destroy(); + return this.eliminate('mask').store('mask:options', options); + }, + + get: function(){ + var mask = this.retrieve('mask'); + if (!mask){ + mask = new Mask(this, this.retrieve('mask:options')); + this.store('mask', mask); + } + return mask; + } + +}; + +Element.implement({ + + mask: function(options){ + if (options) this.set('mask', options); + this.get('mask').show(); + return this; + }, + + unmask: function(){ + this.get('mask').hide(); + return this; + } + +}); + + +/* +--- + +script: Spinner.js + +name: Spinner + +description: Adds a semi-transparent overlay over a dom element with a spinnin ajax icon. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Tween + - Core/Request + - /Class.refactor + - /Mask + +provides: [Spinner] + +... +*/ + +var Spinner = new Class({ + + Extends: Mask, + + Implements: Chain, + + options: {/* + message: false,*/ + 'class': 'spinner', + containerPosition: {}, + content: { + 'class': 'spinner-content' + }, + messageContainer: { + 'class': 'spinner-msg' + }, + img: { + 'class': 'spinner-img' + }, + fxOptions: { + link: 'chain' + } + }, + + initialize: function(target, options){ + this.target = document.id(target) || document.id(document.body); + this.target.store('spinner', this); + this.setOptions(options); + this.render(); + this.inject(); + + // Add this to events for when noFx is true; parent methods handle hide/show. + var deactivate = function(){ this.active = false; }.bind(this); + this.addEvents({ + hide: deactivate, + show: deactivate + }); + }, + + render: function(){ + this.parent(); + + this.element.set('id', this.options.id || 'spinner-' + String.uniqueID()); + + this.content = document.id(this.options.content) || new Element('div', this.options.content); + this.content.inject(this.element); + + if (this.options.message){ + this.msg = document.id(this.options.message) || new Element('p', this.options.messageContainer).appendText(this.options.message); + this.msg.inject(this.content); + } + + if (this.options.img){ + this.img = document.id(this.options.img) || new Element('div', this.options.img); + this.img.inject(this.content); + } + + this.element.set('tween', this.options.fxOptions); + }, + + show: function(noFx){ + if (this.active) return this.chain(this.show.bind(this)); + if (!this.hidden){ + this.callChain.delay(20, this); + return this; + } + + this.active = true; + + return this.parent(noFx); + }, + + showMask: function(noFx){ + var pos = function(){ + this.content.position(Object.merge({ + relativeTo: this.element + }, this.options.containerPosition)); + }.bind(this); + + if (noFx){ + this.parent(); + pos(); + } else { + if (!this.options.style.opacity) this.options.style.opacity = this.element.getStyle('opacity').toFloat(); + this.element.setStyles({ + display: 'block', + opacity: 0 + }).tween('opacity', this.options.style.opacity); + pos(); + this.hidden = false; + this.fireEvent('show'); + this.callChain(); + } + }, + + hide: function(noFx){ + if (this.active) return this.chain(this.hide.bind(this)); + if (this.hidden){ + this.callChain.delay(20, this); + return this; + } + this.active = true; + return this.parent(noFx); + }, + + hideMask: function(noFx){ + if (noFx) return this.parent(); + this.element.tween('opacity', 0).get('tween').chain(function(){ + this.element.setStyle('display', 'none'); + this.hidden = true; + this.fireEvent('hide'); + this.callChain(); + }.bind(this)); + }, + + destroy: function(){ + this.content.destroy(); + this.parent(); + this.target.eliminate('spinner'); + } + +}); + +Request = Class.refactor(Request, { + + options: { + useSpinner: false, + spinnerOptions: {}, + spinnerTarget: false + }, + + initialize: function(options){ + this._send = this.send; + this.send = function(options){ + var spinner = this.getSpinner(); + if (spinner) spinner.chain(this._send.pass(options, this)).show(); + else this._send(options); + return this; + }; + this.previous(options); + }, + + getSpinner: function(){ + if (!this.spinner){ + var update = document.id(this.options.spinnerTarget) || document.id(this.options.update); + if (this.options.useSpinner && update){ + update.set('spinner', this.options.spinnerOptions); + var spinner = this.spinner = update.get('spinner'); + ['complete', 'exception', 'cancel'].each(function(event){ + this.addEvent(event, spinner.hide.bind(spinner)); + }, this); + } + } + return this.spinner; + } + +}); + +Element.Properties.spinner = { + + set: function(options){ + var spinner = this.retrieve('spinner'); + if (spinner) spinner.destroy(); + return this.eliminate('spinner').store('spinner:options', options); + }, + + get: function(){ + var spinner = this.retrieve('spinner'); + if (!spinner){ + spinner = new Spinner(this, this.retrieve('spinner:options')); + this.store('spinner', spinner); + } + return spinner; + } + +}; + +Element.implement({ + + spin: function(options){ + if (options) this.set('spinner', options); + this.get('spinner').show(); + return this; + }, + + unspin: function(){ + this.get('spinner').hide(); + return this; + } + +}); + + +/* +--- + +script: Element.Delegation.js + +name: Element.Delegation + +description: Extends the Element native object to include the delegate method for more efficient event management. + +credits: + - "Event checking based on the work of Daniel Steigerwald. License: MIT-style license. Copyright: Copyright (c) 2008 Daniel Steigerwald, daniel.steigerwald.cz" + +license: MIT-style license + +authors: + - Aaron Newton + - Daniel Steigerwald + +requires: [/MooTools.More, Element.Event.Pseudos] + +provides: [Element.Delegation] + +... +*/ + +(function(){ + +var eventListenerSupport = !(window.attachEvent && !window.addEventListener), + nativeEvents = Element.NativeEvents; + +nativeEvents.focusin = 2; +nativeEvents.focusout = 2; + +var check = function(split, target, event){ + var elementEvent = Element.Events[split.event], condition; + if (elementEvent) condition = elementEvent.condition; + return Slick.match(target, split.value) && (!condition || condition.call(target, event)); +}; + +var bubbleUp = function(split, event, fn){ + for (var target = event.target; target && target != this; target = document.id(target.parentNode)){ + if (target && check(split, target, event)) return fn.call(target, event, target); + } +}; + +var formObserver = function(eventName){ + + var $delegationKey = '$delegation:'; + + return { + base: 'focusin', + + onRemove: function(element){ + element.retrieve($delegationKey + 'forms', []).each(function(el){ + el.retrieve($delegationKey + 'listeners', []).each(function(listener){ + el.removeEvent(eventName, listener); + }); + el.eliminate($delegationKey + eventName + 'listeners') + .eliminate($delegationKey + eventName + 'originalFn'); + }); + }, + + listener: function(split, fn, args, monitor, options){ + var event = args[0], + forms = this.retrieve($delegationKey + 'forms', []), + target = event.target, + form = (target.get('tag') == 'form') ? target : event.target.getParent('form'); + + if (!form) return; + + var formEvents = form.retrieve($delegationKey + 'originalFn', []), + formListeners = form.retrieve($delegationKey + 'listeners', []), + self = this; + + forms.include(form); + this.store($delegationKey + 'forms', forms); + + if (!formEvents.contains(fn)){ + var formListener = function(event){ + bubbleUp.call(self, split, event, fn); + }; + form.addEvent(eventName, formListener); + + formEvents.push(fn); + formListeners.push(formListener); + + form.store($delegationKey + eventName + 'originalFn', formEvents) + .store($delegationKey + eventName + 'listeners', formListeners); + } + } + }; +}; + +var inputObserver = function(eventName){ + return { + base: 'focusin', + listener: function(split, fn, args){ + var events = {blur: function(){ + this.removeEvents(events); + }}, self = this; + events[eventName] = function(event){ + bubbleUp.call(self, split, event, fn); + }; + args[0].target.addEvents(events); + } + }; +}; + +var eventOptions = { + mouseenter: { + base: 'mouseover' + }, + mouseleave: { + base: 'mouseout' + }, + focus: { + base: 'focus' + (eventListenerSupport ? '' : 'in'), + args: [true] + }, + blur: { + base: eventListenerSupport ? 'blur' : 'focusout', + args: [true] + } +}; + +if (!eventListenerSupport) Object.append(eventOptions, { + submit: formObserver('submit'), + reset: formObserver('reset'), + change: inputObserver('change'), + select: inputObserver('select') +}); + +Event.definePseudo('relay', { + listener: function(split, fn, args){ + bubbleUp.call(this, split, args[0], fn); + }, + options: eventOptions +}); + +})(); + + +/* +--- + +script: Form.Request.js + +name: Form.Request + +description: Handles the basic functionality of submitting a form and updating a dom element with the result. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Request.HTML + - /Class.Binds + - /Class.Occlude + - /Spinner + - /String.QueryString + - /Element.Delegation + +provides: [Form.Request] + +... +*/ + +if (!window.Form) window.Form = {}; + +(function(){ + + Form.Request = new Class({ + + Binds: ['onSubmit', 'onFormValidate'], + + Implements: [Options, Events, Class.Occlude], + + options: {/* + onFailure: function(){}, + onSuccess: function(){}, // aliased to onComplete, + onSend: function(){}*/ + requestOptions: { + evalScripts: true, + useSpinner: true, + emulation: false, + link: 'ignore' + }, + sendButtonClicked: true, + extraData: {}, + resetForm: true + }, + + property: 'form.request', + + initialize: function(form, target, options){ + this.element = document.id(form); + if (this.occlude()) return this.occluded; + this.setOptions(options) + .setTarget(target) + .attach(); + }, + + setTarget: function(target){ + this.target = document.id(target); + if (!this.request){ + this.makeRequest(); + } else { + this.request.setOptions({ + update: this.target + }); + } + return this; + }, + + toElement: function(){ + return this.element; + }, + + makeRequest: function(){ + var self = this; + this.request = new Request.HTML(Object.merge({ + update: this.target, + emulation: false, + spinnerTarget: this.element, + method: this.element.get('method') || 'post' + }, this.options.requestOptions)).addEvents({ + success: function(tree, elements, html, javascript){ + ['complete', 'success'].each(function(evt){ + self.fireEvent(evt, [self.target, tree, elements, html, javascript]); + }); + }, + failure: function(){ + self.fireEvent('complete', arguments).fireEvent('failure', arguments); + }, + exception: function(){ + self.fireEvent('failure', arguments); + } + }); + return this.attachReset(); + }, + + attachReset: function(){ + if (!this.options.resetForm) return this; + this.request.addEvent('success', function(){ + Function.attempt(function(){ + this.element.reset(); + }.bind(this)); + if (window.OverText) OverText.update(); + }.bind(this)); + return this; + }, + + attach: function(attach){ + var method = (attach != false) ? 'addEvent' : 'removeEvent'; + this.element[method]('click:relay(button, input[type=submit])', this.saveClickedButton.bind(this)); + + var fv = this.element.retrieve('validator'); + if (fv) fv[method]('onFormValidate', this.onFormValidate); + else this.element[method]('submit', this.onSubmit); + + return this; + }, + + detach: function(){ + return this.attach(false); + }, + + //public method + enable: function(){ + return this.attach(); + }, + + //public method + disable: function(){ + return this.detach(); + }, + + onFormValidate: function(valid, form, event){ + //if there's no event, then this wasn't a submit event + if (!event) return; + var fv = this.element.retrieve('validator'); + if (valid || (fv && !fv.options.stopOnFailure)){ + event.stop(); + this.send(); + } + }, + + onSubmit: function(event){ + var fv = this.element.retrieve('validator'); + if (fv){ + //form validator was created after Form.Request + this.element.removeEvent('submit', this.onSubmit); + fv.addEvent('onFormValidate', this.onFormValidate); + this.element.validate(); + return; + } + if (event) event.stop(); + this.send(); + }, + + saveClickedButton: function(event, target){ + var targetName = target.get('name'); + if (!targetName || !this.options.sendButtonClicked) return; + this.options.extraData[targetName] = target.get('value') || true; + this.clickedCleaner = function(){ + delete this.options.extraData[targetName]; + this.clickedCleaner = function(){}; + }.bind(this); + }, + + clickedCleaner: function(){}, + + send: function(){ + var str = this.element.toQueryString().trim(), + data = Object.toQueryString(this.options.extraData); + + if (str) str += "&" + data; + else str = data; + + this.fireEvent('send', [this.element, str.parseQueryString()]); + this.request.send({ + data: str, + url: this.options.requestOptions.url || this.element.get('action') + }); + this.clickedCleaner(); + return this; + } + + }); + + Element.implement('formUpdate', function(update, options){ + var fq = this.retrieve('form.request'); + if (!fq) { + fq = new Form.Request(this, update, options); + } else { + if (update) fq.setTarget(update); + if (options) fq.setOptions(options).makeRequest(); + } + fq.send(); + return this; + }); + +})(); + + +/* +--- + +script: Fx.Reveal.js + +name: Fx.Reveal + +description: Defines Fx.Reveal, a class that shows and hides elements with a transition. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Morph + - /Element.Shortcuts + - /Element.Measure + +provides: [Fx.Reveal] + +... +*/ + +(function(){ + + +var hideTheseOf = function(object){ + var hideThese = object.options.hideInputs; + if (window.OverText){ + var otClasses = [null]; + OverText.each(function(ot){ + otClasses.include('.' + ot.options.labelClass); + }); + if (otClasses) hideThese += otClasses.join(', '); + } + return (hideThese) ? object.element.getElements(hideThese) : null; +}; + + +Fx.Reveal = new Class({ + + Extends: Fx.Morph, + + options: {/* + onShow: function(thisElement){}, + onHide: function(thisElement){}, + onComplete: function(thisElement){}, + heightOverride: null, + widthOverride: null,*/ + link: 'cancel', + styles: ['padding', 'border', 'margin'], + transitionOpacity: !Browser.ie6, + mode: 'vertical', + display: function(){ + return this.element.get('tag') != 'tr' ? 'block' : 'table-row'; + }, + opacity: 1, + hideInputs: Browser.ie ? 'select, input, textarea, object, embed' : null + }, + + dissolve: function(){ + if (!this.hiding && !this.showing){ + if (this.element.getStyle('display') != 'none'){ + this.hiding = true; + this.showing = false; + this.hidden = true; + this.cssText = this.element.style.cssText; + + var startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + if (this.options.transitionOpacity) startStyles.opacity = this.options.opacity; + + var zero = {}; + Object.each(startStyles, function(style, name){ + zero[name] = [style, 0]; + }); + + this.element.setStyles({ + display: Function.from(this.options.display).call(this), + overflow: 'hidden' + }); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + if (this.hidden){ + this.hiding = false; + this.element.style.cssText = this.cssText; + this.element.setStyle('display', 'none'); + if (hideThese) hideThese.setStyle('visibility', 'visible'); + } + this.fireEvent('hide', this.element); + this.callChain(); + }.bind(this)); + + this.start(zero); + } else { + this.callChain.delay(10, this); + this.fireEvent('complete', this.element); + this.fireEvent('hide', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.dissolve.bind(this)); + } else if (this.options.link == 'cancel' && !this.hiding){ + this.cancel(); + this.dissolve(); + } + return this; + }, + + reveal: function(){ + if (!this.showing && !this.hiding){ + if (this.element.getStyle('display') == 'none'){ + this.hiding = false; + this.showing = true; + this.hidden = false; + this.cssText = this.element.style.cssText; + + var startStyles; + this.element.measure(function(){ + startStyles = this.element.getComputedSize({ + styles: this.options.styles, + mode: this.options.mode + }); + }.bind(this)); + if (this.options.heightOverride != null) startStyles.height = this.options.heightOverride.toInt(); + if (this.options.widthOverride != null) startStyles.width = this.options.widthOverride.toInt(); + if (this.options.transitionOpacity){ + this.element.setStyle('opacity', 0); + startStyles.opacity = this.options.opacity; + } + + var zero = { + height: 0, + display: Function.from(this.options.display).call(this) + }; + Object.each(startStyles, function(style, name){ + zero[name] = 0; + }); + zero.overflow = 'hidden'; + + this.element.setStyles(zero); + + var hideThese = hideTheseOf(this); + if (hideThese) hideThese.setStyle('visibility', 'hidden'); + + this.$chain.unshift(function(){ + this.element.style.cssText = this.cssText; + this.element.setStyle('display', Function.from(this.options.display).call(this)); + if (!this.hidden) this.showing = false; + if (hideThese) hideThese.setStyle('visibility', 'visible'); + this.callChain(); + this.fireEvent('show', this.element); + }.bind(this)); + + this.start(startStyles); + } else { + this.callChain(); + this.fireEvent('complete', this.element); + this.fireEvent('show', this.element); + } + } else if (this.options.link == 'chain'){ + this.chain(this.reveal.bind(this)); + } else if (this.options.link == 'cancel' && !this.showing){ + this.cancel(); + this.reveal(); + } + return this; + }, + + toggle: function(){ + if (this.element.getStyle('display') == 'none'){ + this.reveal(); + } else { + this.dissolve(); + } + return this; + }, + + cancel: function(){ + this.parent.apply(this, arguments); + if (this.cssText != null) this.element.style.cssText = this.cssText; + this.hiding = false; + this.showing = false; + return this; + } + +}); + +Element.Properties.reveal = { + + set: function(options){ + this.get('reveal').cancel().setOptions(options); + return this; + }, + + get: function(){ + var reveal = this.retrieve('reveal'); + if (!reveal){ + reveal = new Fx.Reveal(this); + this.store('reveal', reveal); + } + return reveal; + } + +}; + +Element.Properties.dissolve = Element.Properties.reveal; + +Element.implement({ + + reveal: function(options){ + this.get('reveal').setOptions(options).reveal(); + return this; + }, + + dissolve: function(options){ + this.get('reveal').setOptions(options).dissolve(); + return this; + }, + + nix: function(options){ + var params = Array.link(arguments, {destroy: Type.isBoolean, options: Type.isObject}); + this.get('reveal').setOptions(options).dissolve().chain(function(){ + this[params.destroy ? 'destroy' : 'dispose'](); + }.bind(this)); + return this; + }, + + wink: function(){ + var params = Array.link(arguments, {duration: Type.isNumber, options: Type.isObject}); + var reveal = this.get('reveal').setOptions(params.options); + reveal.reveal().chain(function(){ + (function(){ + reveal.dissolve(); + }).delay(params.duration || 2000); + }); + } + +}); + +})(); + + +/* +--- + +script: Form.Request.Append.js + +name: Form.Request.Append + +description: Handles the basic functionality of submitting a form and updating a dom element with the result. The result is appended to the DOM element instead of replacing its contents. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Form.Request + - /Fx.Reveal + - /Elements.from + +provides: [Form.Request.Append] + +... +*/ + +Form.Request.Append = new Class({ + + Extends: Form.Request, + + options: { + //onBeforeEffect: function(){}, + useReveal: true, + revealOptions: {}, + inject: 'bottom' + }, + + makeRequest: function(){ + this.request = new Request.HTML(Object.merge({ + url: this.element.get('action'), + method: this.element.get('method') || 'post', + spinnerTarget: this.element + }, this.options.requestOptions, { + evalScripts: false + }) + ).addEvents({ + success: function(tree, elements, html, javascript){ + var container; + var kids = Elements.from(html); + if (kids.length == 1){ + container = kids[0]; + } else { + container = new Element('div', { + styles: { + display: 'none' + } + }).adopt(kids); + } + container.inject(this.target, this.options.inject); + if (this.options.requestOptions.evalScripts) Browser.exec(javascript); + this.fireEvent('beforeEffect', container); + var finish = function(){ + this.fireEvent('success', [container, this.target, tree, elements, html, javascript]); + }.bind(this); + if (this.options.useReveal){ + container.set('reveal', this.options.revealOptions).get('reveal').chain(finish); + container.reveal(); + } else { + finish(); + } + }.bind(this), + failure: function(xhr){ + this.fireEvent('failure', xhr); + }.bind(this) + }); + this.attachReset(); + } + +}); + + +/* +--- + +name: Locale.en-US.Form.Validator + +description: Form Validator messages for English. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Locale + +provides: [Locale.en-US.Form.Validator] + +... +*/ + +Locale.define('en-US', 'FormValidator', { + + required: 'This field is required.', + minLength: 'Please enter at least {minLength} characters (you entered {length} characters).', + maxLength: 'Please enter no more than {maxLength} characters (you entered {length} characters).', + integer: 'Please enter an integer in this field. Numbers with decimals (e.g. 1.25) are not permitted.', + numeric: 'Please enter only numeric values in this field (i.e. "1" or "1.1" or "-1" or "-1.1").', + digits: 'Please use numbers and punctuation only in this field (for example, a phone number with dashes or dots is permitted).', + alpha: 'Please use only letters (a-z) within this field. No spaces or other characters are allowed.', + alphanum: 'Please use only letters (a-z) or numbers (0-9) in this field. No spaces or other characters are allowed.', + dateSuchAs: 'Please enter a valid date such as {date}', + dateInFormatMDY: 'Please enter a valid date such as MM/DD/YYYY (i.e. "12/31/1999")', + email: 'Please enter a valid email address. For example "fred@domain.com".', + url: 'Please enter a valid URL such as http://www.example.com.', + currencyDollar: 'Please enter a valid $ amount. For example $100.00 .', + oneRequired: 'Please enter something for at least one of these inputs.', + errorPrefix: 'Error: ', + warningPrefix: 'Warning: ', + + // Form.Validator.Extras + noSpace: 'There can be no spaces in this input.', + reqChkByNode: 'No items are selected.', + requiredChk: 'This field is required.', + reqChkByName: 'Please select a {label}.', + match: 'This field needs to match the {matchName} field', + startDate: 'the start date', + endDate: 'the end date', + currendDate: 'the current date', + afterDate: 'The date should be the same or after {label}.', + beforeDate: 'The date should be the same or before {label}.', + startMonth: 'Please select a start month', + sameMonth: 'These two dates must be in the same month - you must change one or the other.', + creditcard: 'The credit card number entered is invalid. Please check the number and try again. {length} digits entered.' + +}); + + +/* +--- + +script: Form.Validator.js + +name: Form.Validator + +description: A css-class based form validation system. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Slick.Finder + - Core/Element.Event + - Core/Element.Style + - Core/JSON + - /Locale + - /Class.Binds + - /Date + - /Element.Forms + - /Locale.en-US.Form.Validator + - /Element.Shortcuts + +provides: [Form.Validator, InputValidator, FormValidator.BaseValidators] + +... +*/ +if (!window.Form) window.Form = {}; + +var InputValidator = this.InputValidator = new Class({ + + Implements: [Options], + + options: { + errorMsg: 'Validation failed.', + test: Function.from(true) + }, + + initialize: function(className, options){ + this.setOptions(options); + this.className = className; + }, + + test: function(field, props){ + field = document.id(field); + return (field) ? this.options.test(field, props || this.getProps(field)) : false; + }, + + getError: function(field, props){ + field = document.id(field); + var err = this.options.errorMsg; + if (typeOf(err) == 'function') err = err(field, props || this.getProps(field)); + return err; + }, + + getProps: function(field){ + field = document.id(field); + return (field) ? field.get('validatorProps') : {}; + } + +}); + +Element.Properties.validators = { + + get: function(){ + return (this.get('data-validators') || this.className).clean().split(' '); + } + +}; + +Element.Properties.validatorProps = { + + set: function(props){ + return this.eliminate('$moo:validatorProps').store('$moo:validatorProps', props); + }, + + get: function(props){ + if (props) this.set(props); + if (this.retrieve('$moo:validatorProps')) return this.retrieve('$moo:validatorProps'); + if (this.getProperty('data-validator-properties') || this.getProperty('validatorProps')){ + try { + this.store('$moo:validatorProps', JSON.decode(this.getProperty('validatorProps') || this.getProperty('data-validator-properties'))); + }catch(e){ + return {}; + } + } else { + var vals = this.get('validators').filter(function(cls){ + return cls.test(':'); + }); + if (!vals.length){ + this.store('$moo:validatorProps', {}); + } else { + props = {}; + vals.each(function(cls){ + var split = cls.split(':'); + if (split[1]){ + try { + props[split[0]] = JSON.decode(split[1]); + } catch(e){} + } + }); + this.store('$moo:validatorProps', props); + } + } + return this.retrieve('$moo:validatorProps'); + } + +}; + +Form.Validator = new Class({ + + Implements: [Options, Events], + + Binds: ['onSubmit'], + + options: {/* + onFormValidate: function(isValid, form, event){}, + onElementValidate: function(isValid, field, className, warn){}, + onElementPass: function(field){}, + onElementFail: function(field, validatorsFailed){}, */ + fieldSelectors: 'input, select, textarea', + ignoreHidden: true, + ignoreDisabled: true, + useTitles: false, + evaluateOnSubmit: true, + evaluateFieldsOnBlur: true, + evaluateFieldsOnChange: true, + serial: true, + stopOnFailure: true, + warningPrefix: function(){ + return Form.Validator.getMsg('warningPrefix') || 'Warning: '; + }, + errorPrefix: function(){ + return Form.Validator.getMsg('errorPrefix') || 'Error: '; + } + }, + + initialize: function(form, options){ + this.setOptions(options); + this.element = document.id(form); + this.element.store('validator', this); + this.warningPrefix = Function.from(this.options.warningPrefix)(); + this.errorPrefix = Function.from(this.options.errorPrefix)(); + if (this.options.evaluateOnSubmit) this.element.addEvent('submit', this.onSubmit); + if (this.options.evaluateFieldsOnBlur || this.options.evaluateFieldsOnChange) this.watchFields(this.getFields()); + }, + + toElement: function(){ + return this.element; + }, + + getFields: function(){ + return (this.fields = this.element.getElements(this.options.fieldSelectors)); + }, + + watchFields: function(fields){ + fields.each(function(el){ + if (this.options.evaluateFieldsOnBlur) + el.addEvent('blur', this.validationMonitor.pass([el, false], this)); + if (this.options.evaluateFieldsOnChange) + el.addEvent('change', this.validationMonitor.pass([el, true], this)); + }, this); + }, + + validationMonitor: function(){ + clearTimeout(this.timer); + this.timer = this.validateField.delay(50, this, arguments); + }, + + onSubmit: function(event){ + if (this.validate(event)) this.reset(); + }, + + reset: function(){ + this.getFields().each(this.resetField, this); + return this; + }, + + validate: function(event){ + var result = this.getFields().map(function(field){ + return this.validateField(field, true); + }, this).every(function(v){ + return v; + }); + this.fireEvent('formValidate', [result, this.element, event]); + if (this.options.stopOnFailure && !result && event) event.preventDefault(); + return result; + }, + + validateField: function(field, force){ + if (this.paused) return true; + field = document.id(field); + var passed = !field.hasClass('validation-failed'); + var failed, warned; + if (this.options.serial && !force){ + failed = this.element.getElement('.validation-failed'); + warned = this.element.getElement('.warning'); + } + if (field && (!failed || force || field.hasClass('validation-failed') || (failed && !this.options.serial))){ + var validationTypes = field.get('validators'); + var validators = validationTypes.some(function(cn){ + return this.getValidator(cn); + }, this); + var validatorsFailed = []; + validationTypes.each(function(className){ + if (className && !this.test(className, field)) validatorsFailed.include(className); + }, this); + passed = validatorsFailed.length === 0; + if (validators && !this.hasValidator(field, 'warnOnly')){ + if (passed){ + field.addClass('validation-passed').removeClass('validation-failed'); + this.fireEvent('elementPass', [field]); + } else { + field.addClass('validation-failed').removeClass('validation-passed'); + this.fireEvent('elementFail', [field, validatorsFailed]); + } + } + if (!warned){ + var warnings = validationTypes.some(function(cn){ + if (cn.test('^warn')) + return this.getValidator(cn.replace(/^warn-/,'')); + else return null; + }, this); + field.removeClass('warning'); + var warnResult = validationTypes.map(function(cn){ + if (cn.test('^warn')) + return this.test(cn.replace(/^warn-/,''), field, true); + else return null; + }, this); + } + } + return passed; + }, + + test: function(className, field, warn){ + field = document.id(field); + if ((this.options.ignoreHidden && !field.isVisible()) || (this.options.ignoreDisabled && field.get('disabled'))) return true; + var validator = this.getValidator(className); + if (warn != null) warn = false; + if (this.hasValidator(field, 'warnOnly')) warn = true; + var isValid = this.hasValidator(field, 'ignoreValidation') || (validator ? validator.test(field) : true); + if (validator && field.isVisible()) this.fireEvent('elementValidate', [isValid, field, className, warn]); + if (warn) return true; + return isValid; + }, + + hasValidator: function(field, value){ + return field.get('validators').contains(value); + }, + + resetField: function(field){ + field = document.id(field); + if (field){ + field.get('validators').each(function(className){ + if (className.test('^warn-')) className = className.replace(/^warn-/, ''); + field.removeClass('validation-failed'); + field.removeClass('warning'); + field.removeClass('validation-passed'); + }, this); + } + return this; + }, + + stop: function(){ + this.paused = true; + return this; + }, + + start: function(){ + this.paused = false; + return this; + }, + + ignoreField: function(field, warn){ + field = document.id(field); + if (field){ + this.enforceField(field); + if (warn) field.addClass('warnOnly'); + else field.addClass('ignoreValidation'); + } + return this; + }, + + enforceField: function(field){ + field = document.id(field); + if (field) field.removeClass('warnOnly').removeClass('ignoreValidation'); + return this; + } + +}); + +Form.Validator.getMsg = function(key){ + return Locale.get('FormValidator.' + key); +}; + +Form.Validator.adders = { + + validators:{}, + + add : function(className, options){ + this.validators[className] = new InputValidator(className, options); + //if this is a class (this method is used by instances of Form.Validator and the Form.Validator namespace) + //extend these validators into it + //this allows validators to be global and/or per instance + if (!this.initialize){ + this.implement({ + validators: this.validators + }); + } + }, + + addAllThese : function(validators){ + Array.from(validators).each(function(validator){ + this.add(validator[0], validator[1]); + }, this); + }, + + getValidator: function(className){ + return this.validators[className.split(':')[0]]; + } + +}; + +Object.append(Form.Validator, Form.Validator.adders); + +Form.Validator.implement(Form.Validator.adders); + +Form.Validator.add('IsEmpty', { + + errorMsg: false, + test: function(element){ + if (element.type == 'select-one' || element.type == 'select') + return !(element.selectedIndex >= 0 && element.options[element.selectedIndex].value != ''); + else + return ((element.get('value') == null) || (element.get('value').length == 0)); + } + +}); + +Form.Validator.addAllThese([ + + ['required', { + errorMsg: function(){ + return Form.Validator.getMsg('required'); + }, + test: function(element){ + return !Form.Validator.getValidator('IsEmpty').test(element); + } + }], + + ['minLength', { + errorMsg: function(element, props){ + if (typeOf(props.minLength) != 'null') + return Form.Validator.getMsg('minLength').substitute({minLength:props.minLength,length:element.get('value').length }); + else return ''; + }, + test: function(element, props){ + if (typeOf(props.minLength) != 'null') return (element.get('value').length >= (props.minLength || 0)); + else return true; + } + }], + + ['maxLength', { + errorMsg: function(element, props){ + //props is {maxLength:10} + if (typeOf(props.maxLength) != 'null') + return Form.Validator.getMsg('maxLength').substitute({maxLength:props.maxLength,length:element.get('value').length }); + else return ''; + }, + test: function(element, props){ + return element.get('value').length <= (props.maxLength || 10000); + } + }], + + ['validate-integer', { + errorMsg: Form.Validator.getMsg.pass('integer'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^(-?[1-9]\d*|0)$/).test(element.get('value')); + } + }], + + ['validate-numeric', { + errorMsg: Form.Validator.getMsg.pass('numeric'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || + (/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value')); + } + }], + + ['validate-digits', { + errorMsg: Form.Validator.getMsg.pass('digits'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^[\d() .:\-\+#]+$/.test(element.get('value'))); + } + }], + + ['validate-alpha', { + errorMsg: Form.Validator.getMsg.pass('alpha'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^[a-zA-Z]+$/).test(element.get('value')); + } + }], + + ['validate-alphanum', { + errorMsg: Form.Validator.getMsg.pass('alphanum'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || !(/\W/).test(element.get('value')); + } + }], + + ['validate-date', { + errorMsg: function(element, props){ + if (Date.parse){ + var format = props.dateFormat || '%x'; + return Form.Validator.getMsg('dateSuchAs').substitute({date: new Date().format(format)}); + } else { + return Form.Validator.getMsg('dateInFormatMDY'); + } + }, + test: function(element, props){ + if (Form.Validator.getValidator('IsEmpty').test(element)) return true; + var dateLocale = Locale.getCurrent().sets.Date, + dateNouns = new RegExp([dateLocale.days, dateLocale.days_abbr, dateLocale.months, dateLocale.months_abbr].flatten().join('|'), 'i'), + value = element.get('value'), + wordsInValue = value.match(/[a-z]+/gi); + + if (wordsInValue && !wordsInValue.every(dateNouns.exec, dateNouns)) return false; + + var date = Date.parse(value), + format = props.dateFormat || '%x', + formatted = date.format(format); + + if (formatted != 'invalid date') element.set('value', formatted); + return date.isValid(); + } + }], + + ['validate-email', { + errorMsg: Form.Validator.getMsg.pass('email'), + test: function(element){ + /* + var chars = "[a-z0-9!#$%&'*+/=?^_`{|}~-]", + local = '(?:' + chars + '\\.?){0,63}' + chars, + + label = '[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?', + hostname = '(?:' + label + '\\.)*' + label; + + octet = '(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)', + ipv4 = '\\[(?:' + octet + '\\.){3}' + octet + '\\]', + + domain = '(?:' + hostname + '|' + ipv4 + ')'; + + var regex = new RegExp('^' + local + '@' + domain + '$', 'i'); + */ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+\/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value')); + } + }], + + ['validate-url', { + errorMsg: Form.Validator.getMsg.pass('url'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(element.get('value')); + } + }], + + ['validate-currency-dollar', { + errorMsg: Form.Validator.getMsg.pass('currencyDollar'), + test: function(element){ + return Form.Validator.getValidator('IsEmpty').test(element) || (/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value')); + } + }], + + ['validate-one-required', { + errorMsg: Form.Validator.getMsg.pass('oneRequired'), + test: function(element, props){ + var p = document.id(props['validate-one-required']) || element.getParent(props['validate-one-required']); + return p.getElements('input').some(function(el){ + if (['checkbox', 'radio'].contains(el.get('type'))) return el.get('checked'); + return el.get('value'); + }); + } + }] + +]); + +Element.Properties.validator = { + + set: function(options){ + this.get('validator').setOptions(options); + }, + + get: function(){ + var validator = this.retrieve('validator'); + if (!validator){ + validator = new Form.Validator(this); + this.store('validator', validator); + } + return validator; + } + +}; + +Element.implement({ + + validate: function(options){ + if (options) this.set('validator', options); + return this.get('validator').validate(); + } + +}); + + + + + + + +/* +--- + +script: Form.Validator.Inline.js + +name: Form.Validator.Inline + +description: Extends Form.Validator to add inline messages. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Form.Validator + +provides: [Form.Validator.Inline] + +... +*/ + +Form.Validator.Inline = new Class({ + + Extends: Form.Validator, + + options: { + showError: function(errorElement){ + if (errorElement.reveal) errorElement.reveal(); + else errorElement.setStyle('display', 'block'); + }, + hideError: function(errorElement){ + if (errorElement.dissolve) errorElement.dissolve(); + else errorElement.setStyle('display', 'none'); + }, + scrollToErrorsOnSubmit: true, + scrollToErrorsOnBlur: false, + scrollToErrorsOnChange: false, + scrollFxOptions: { + transition: 'quad:out', + offset: { + y: -20 + } + } + }, + + initialize: function(form, options){ + this.parent(form, options); + this.addEvent('onElementValidate', function(isValid, field, className, warn){ + var validator = this.getValidator(className); + if (!isValid && validator.getError(field)){ + if (warn) field.addClass('warning'); + var advice = this.makeAdvice(className, field, validator.getError(field), warn); + this.insertAdvice(advice, field); + this.showAdvice(className, field); + } else { + this.hideAdvice(className, field); + } + }); + }, + + makeAdvice: function(className, field, error, warn){ + var errorMsg = (warn) ? this.warningPrefix : this.errorPrefix; + errorMsg += (this.options.useTitles) ? field.title || error:error; + var cssClass = (warn) ? 'warning-advice' : 'validation-advice'; + var advice = this.getAdvice(className, field); + if (advice){ + advice = advice.set('html', errorMsg); + } else { + advice = new Element('div', { + html: errorMsg, + styles: { display: 'none' }, + id: 'advice-' + className.split(':')[0] + '-' + this.getFieldId(field) + }).addClass(cssClass); + } + field.store('$moo:advice-' + className, advice); + return advice; + }, + + getFieldId : function(field){ + return field.id ? field.id : field.id = 'input_' + field.name; + }, + + showAdvice: function(className, field){ + var advice = this.getAdvice(className, field); + if ( + advice && + !field.retrieve('$moo:' + this.getPropName(className)) && + ( + advice.getStyle('display') == 'none' || + advice.getStyle('visiblity') == 'hidden' || + advice.getStyle('opacity') == 0 + ) + ){ + field.store('$moo:' + this.getPropName(className), true); + this.options.showError(advice); + this.fireEvent('showAdvice', [field, advice, className]); + } + }, + + hideAdvice: function(className, field){ + var advice = this.getAdvice(className, field); + if (advice && field.retrieve('$moo:' + this.getPropName(className))){ + field.store('$moo:' + this.getPropName(className), false); + this.options.hideError(advice); + this.fireEvent('hideAdvice', [field, advice, className]); + } + }, + + getPropName: function(className){ + return 'advice' + className; + }, + + resetField: function(field){ + field = document.id(field); + if (!field) return this; + this.parent(field); + field.get('validators').each(function(className){ + this.hideAdvice(className, field); + }, this); + return this; + }, + + getAllAdviceMessages: function(field, force){ + var advice = []; + if (field.hasClass('ignoreValidation') && !force) return advice; + var validators = field.get('validators').some(function(cn){ + var warner = cn.test('^warn-') || field.hasClass('warnOnly'); + if (warner) cn = cn.replace(/^warn-/, ''); + var validator = this.getValidator(cn); + if (!validator) return; + advice.push({ + message: validator.getError(field), + warnOnly: warner, + passed: validator.test(), + validator: validator + }); + }, this); + return advice; + }, + + getAdvice: function(className, field){ + return field.retrieve('$moo:advice-' + className); + }, + + insertAdvice: function(advice, field){ + //Check for error position prop + var props = field.get('validatorProps'); + //Build advice + if (!props.msgPos || !document.id(props.msgPos)){ + if (field.type && field.type.toLowerCase() == 'radio') field.getParent().adopt(advice); + else advice.inject(document.id(field), 'after'); + } else { + document.id(props.msgPos).grab(advice); + } + }, + + validateField: function(field, force, scroll){ + var result = this.parent(field, force); + if (((this.options.scrollToErrorsOnSubmit && scroll == null) || scroll) && !result){ + var failed = document.id(this).getElement('.validation-failed'); + var par = document.id(this).getParent(); + while (par != document.body && par.getScrollSize().y == par.getSize().y){ + par = par.getParent(); + } + var fx = par.retrieve('$moo:fvScroller'); + if (!fx && window.Fx && Fx.Scroll){ + fx = new Fx.Scroll(par, this.options.scrollFxOptions); + par.store('$moo:fvScroller', fx); + } + if (failed){ + if (fx) fx.toElement(failed); + else par.scrollTo(par.getScroll().x, failed.getPosition(par).y - 20); + } + } + return result; + }, + + watchFields: function(fields){ + fields.each(function(el){ + if (this.options.evaluateFieldsOnBlur){ + el.addEvent('blur', this.validationMonitor.pass([el, false, this.options.scrollToErrorsOnBlur], this)); + } + if (this.options.evaluateFieldsOnChange){ + el.addEvent('change', this.validationMonitor.pass([el, true, this.options.scrollToErrorsOnChange], this)); + } + }, this); + } + +}); + + +/* +--- + +script: Form.Validator.Extras.js + +name: Form.Validator.Extras + +description: Additional validators for the Form.Validator class. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Form.Validator + +provides: [Form.Validator.Extras] + +... +*/ +Form.Validator.addAllThese([ + + ['validate-enforce-oncheck', { + test: function(element, props){ + var fv = element.getParent('form').retrieve('validator'); + if (!fv) return true; + (props.toEnforce || document.id(props.enforceChildrenOf).getElements('input, select, textarea')).map(function(item){ + if (element.checked){ + fv.enforceField(item); + } else { + fv.ignoreField(item); + fv.resetField(item); + } + }); + return true; + } + }], + + ['validate-ignore-oncheck', { + test: function(element, props){ + var fv = element.getParent('form').retrieve('validator'); + if (!fv) return true; + (props.toIgnore || document.id(props.ignoreChildrenOf).getElements('input, select, textarea')).each(function(item){ + if (element.checked){ + fv.ignoreField(item); + fv.resetField(item); + } else { + fv.enforceField(item); + } + }); + return true; + } + }], + + ['validate-nospace', { + errorMsg: function(){ + return Form.Validator.getMsg('noSpace'); + }, + test: function(element, props){ + return !element.get('value').test(/\s/); + } + }], + + ['validate-toggle-oncheck', { + test: function(element, props){ + var fv = element.getParent('form').retrieve('validator'); + if (!fv) return true; + var eleArr = props.toToggle || document.id(props.toToggleChildrenOf).getElements('input, select, textarea'); + if (!element.checked){ + eleArr.each(function(item){ + fv.ignoreField(item); + fv.resetField(item); + }); + } else { + eleArr.each(function(item){ + fv.enforceField(item); + }); + } + return true; + } + }], + + ['validate-reqchk-bynode', { + errorMsg: function(){ + return Form.Validator.getMsg('reqChkByNode'); + }, + test: function(element, props){ + return (document.id(props.nodeId).getElements(props.selector || 'input[type=checkbox], input[type=radio]')).some(function(item){ + return item.checked; + }); + } + }], + + ['validate-required-check', { + errorMsg: function(element, props){ + return props.useTitle ? element.get('title') : Form.Validator.getMsg('requiredChk'); + }, + test: function(element, props){ + return !!element.checked; + } + }], + + ['validate-reqchk-byname', { + errorMsg: function(element, props){ + return Form.Validator.getMsg('reqChkByName').substitute({label: props.label || element.get('type')}); + }, + test: function(element, props){ + var grpName = props.groupName || element.get('name'); + var oneCheckedItem = $$(document.getElementsByName(grpName)).some(function(item, index){ + return item.checked; + }); + var fv = element.getParent('form').retrieve('validator'); + if (oneCheckedItem && fv) fv.resetField(element); + return oneCheckedItem; + } + }], + + ['validate-match', { + errorMsg: function(element, props){ + return Form.Validator.getMsg('match').substitute({matchName: props.matchName || document.id(props.matchInput).get('name')}); + }, + test: function(element, props){ + var eleVal = element.get('value'); + var matchVal = document.id(props.matchInput) && document.id(props.matchInput).get('value'); + return eleVal && matchVal ? eleVal == matchVal : true; + } + }], + + ['validate-after-date', { + errorMsg: function(element, props){ + return Form.Validator.getMsg('afterDate').substitute({ + label: props.afterLabel || (props.afterElement ? Form.Validator.getMsg('startDate') : Form.Validator.getMsg('currentDate')) + }); + }, + test: function(element, props){ + var start = document.id(props.afterElement) ? Date.parse(document.id(props.afterElement).get('value')) : new Date(); + var end = Date.parse(element.get('value')); + return end && start ? end >= start : true; + } + }], + + ['validate-before-date', { + errorMsg: function(element, props){ + return Form.Validator.getMsg('beforeDate').substitute({ + label: props.beforeLabel || (props.beforeElement ? Form.Validator.getMsg('endDate') : Form.Validator.getMsg('currentDate')) + }); + }, + test: function(element, props){ + var start = Date.parse(element.get('value')); + var end = document.id(props.beforeElement) ? Date.parse(document.id(props.beforeElement).get('value')) : new Date(); + return end && start ? end >= start : true; + } + }], + + ['validate-custom-required', { + errorMsg: function(){ + return Form.Validator.getMsg('required'); + }, + test: function(element, props){ + return element.get('value') != props.emptyValue; + } + }], + + ['validate-same-month', { + errorMsg: function(element, props){ + var startMo = document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value'); + var eleVal = element.get('value'); + if (eleVal != '') return Form.Validator.getMsg(startMo ? 'sameMonth' : 'startMonth'); + }, + test: function(element, props){ + var d1 = Date.parse(element.get('value')); + var d2 = Date.parse(document.id(props.sameMonthAs) && document.id(props.sameMonthAs).get('value')); + return d1 && d2 ? d1.format('%B') == d2.format('%B') : true; + } + }], + + + ['validate-cc-num', { + errorMsg: function(element){ + var ccNum = element.get('value').replace(/[^0-9]/g, ''); + return Form.Validator.getMsg('creditcard').substitute({length: ccNum.length}); + }, + test: function(element){ + // required is a different test + if (Form.Validator.getValidator('IsEmpty').test(element)) return true; + + // Clean number value + var ccNum = element.get('value'); + ccNum = ccNum.replace(/[^0-9]/g, ''); + + var valid_type = false; + + if (ccNum.test(/^4[0-9]{12}([0-9]{3})?$/)) valid_type = 'Visa'; + else if (ccNum.test(/^5[1-5]([0-9]{14})$/)) valid_type = 'Master Card'; + else if (ccNum.test(/^3[47][0-9]{13}$/)) valid_type = 'American Express'; + else if (ccNum.test(/^6011[0-9]{12}$/)) valid_type = 'Discover'; + + if (valid_type){ + var sum = 0; + var cur = 0; + + for (var i=ccNum.length-1; i>=0; --i){ + cur = ccNum.charAt(i).toInt(); + if (cur == 0) continue; + + if ((ccNum.length-i) % 2 == 0) cur += cur; + if (cur > 9){ + cur = cur.toString().charAt(0).toInt() + cur.toString().charAt(1).toInt(); + } + + sum += cur; + } + if ((sum % 10) == 0) return true; + } + + var chunks = ''; + while (ccNum != ''){ + chunks += ' ' + ccNum.substr(0,4); + ccNum = ccNum.substr(4); + } + + element.getParent('form').retrieve('validator').ignoreField(element); + element.set('value', chunks.clean()); + element.getParent('form').retrieve('validator').enforceField(element); + return false; + } + }] + + +]); + + +/* +--- + +script: OverText.js + +name: OverText + +description: Shows text over an input that disappears when the user clicks into it. The text remains hidden if the user adds a value. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - Class.Binds + - Class.Occlude + - Element.Position + - Element.Shortcuts + +provides: [OverText] + +... +*/ + +var OverText = new Class({ + + Implements: [Options, Events, Class.Occlude], + + Binds: ['reposition', 'assert', 'focus', 'hide'], + + options: {/* + textOverride: null, + onFocus: function(){}, + onTextHide: function(textEl, inputEl){}, + onTextShow: function(textEl, inputEl){}, */ + element: 'label', + labelClass: 'overTxtLabel', + positionOptions: { + position: 'upperLeft', + edge: 'upperLeft', + offset: { + x: 4, + y: 2 + } + }, + poll: false, + pollInterval: 250, + wrap: false + }, + + property: 'OverText', + + initialize: function(element, options){ + element = this.element = document.id(element); + + if (this.occlude()) return this.occluded; + this.setOptions(options); + + this.attach(element); + OverText.instances.push(this); + + if (this.options.poll) this.poll(); + }, + + toElement: function(){ + return this.element; + }, + + attach: function(){ + var element = this.element, + options = this.options, + value = options.textOverride || element.get('alt') || element.get('title'); + + if (!value) return this; + + var text = this.text = new Element(options.element, { + 'class': options.labelClass, + styles: { + lineHeight: 'normal', + position: 'absolute', + cursor: 'text' + }, + html: value, + events: { + click: this.hide.pass(options.element == 'label', this) + } + }).inject(element, 'after'); + + if (options.element == 'label'){ + if (!element.get('id')) element.set('id', 'input_' + String.uniqueID()); + text.set('for', element.get('id')); + } + + if (options.wrap){ + this.textHolder = new Element('div.overTxtWrapper', { + styles: { + lineHeight: 'normal', + position: 'relative' + } + }).grab(text).inject(element, 'before'); + } + + return this.enable(); + }, + + destroy: function(){ + this.element.eliminate(this.property); // Class.Occlude storage + this.disable(); + if (this.text) this.text.destroy(); + if (this.textHolder) this.textHolder.destroy(); + return this; + }, + + disable: function(){ + this.element.removeEvents({ + focus: this.focus, + blur: this.assert, + change: this.assert + }); + window.removeEvent('resize', this.reposition); + this.hide(true, true); + return this; + }, + + enable: function(){ + this.element.addEvents({ + focus: this.focus, + blur: this.assert, + change: this.assert + }); + window.addEvent('resize', this.reposition); + this.assert(true); + this.reposition(); + return this; + }, + + wrap: function(){ + if (this.options.element == 'label'){ + if (!this.element.get('id')) this.element.set('id', 'input_' + String.uniqueID()); + this.text.set('for', this.element.get('id')); + } + }, + + startPolling: function(){ + this.pollingPaused = false; + return this.poll(); + }, + + poll: function(stop){ + //start immediately + //pause on focus + //resumeon blur + if (this.poller && !stop) return this; + if (stop){ + clearInterval(this.poller); + } else { + this.poller = (function(){ + if (!this.pollingPaused) this.assert(true); + }).periodical(this.options.pollInterval, this); + } + + return this; + }, + + stopPolling: function(){ + this.pollingPaused = true; + return this.poll(true); + }, + + focus: function(){ + if (this.text && (!this.text.isDisplayed() || this.element.get('disabled'))) return this; + return this.hide(); + }, + + hide: function(suppressFocus, force){ + if (this.text && (this.text.isDisplayed() && (!this.element.get('disabled') || force))){ + this.text.hide(); + this.fireEvent('textHide', [this.text, this.element]); + this.pollingPaused = true; + if (!suppressFocus){ + try { + this.element.fireEvent('focus'); + this.element.focus(); + } catch(e){} //IE barfs if you call focus on hidden elements + } + } + return this; + }, + + show: function(){ + if (this.text && !this.text.isDisplayed()){ + this.text.show(); + this.reposition(); + this.fireEvent('textShow', [this.text, this.element]); + this.pollingPaused = false; + } + return this; + }, + + test: function(){ + return !this.element.get('value'); + }, + + assert: function(suppressFocus){ + return this[this.test() ? 'show' : 'hide'](suppressFocus); + }, + + reposition: function(){ + this.assert(true); + if (!this.element.isVisible()) return this.stopPolling().hide(); + if (this.text && this.test()){ + this.text.position(Object.merge(this.options.positionOptions, { + relativeTo: this.element + })); + } + return this; + } + +}); + +OverText.instances = []; + +Object.append(OverText, { + + each: function(fn){ + return OverText.instances.each(function(ot, i){ + if (ot.element && ot.text) fn.call(OverText, ot, i); + }); + }, + + update: function(){ + + return OverText.each(function(ot){ + return ot.reposition(); + }); + + }, + + hideAll: function(){ + + return OverText.each(function(ot){ + return ot.hide(true, true); + }); + + }, + + showAll: function(){ + return OverText.each(function(ot){ + return ot.show(); + }); + } + +}); + + + +/* +--- + +script: Fx.Elements.js + +name: Fx.Elements + +description: Effect to change any number of CSS properties of any number of Elements. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Fx.CSS + - /MooTools.More + +provides: [Fx.Elements] + +... +*/ + +Fx.Elements = new Class({ + + Extends: Fx.CSS, + + initialize: function(elements, options){ + this.elements = this.subject = $$(elements); + this.parent(options); + }, + + compute: function(from, to, delta){ + var now = {}; + + for (var i in from){ + var iFrom = from[i], iTo = to[i], iNow = now[i] = {}; + for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta); + } + + return now; + }, + + set: function(now){ + for (var i in now){ + if (!this.elements[i]) continue; + + var iNow = now[i]; + for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit); + } + + return this; + }, + + start: function(obj){ + if (!this.check(obj)) return this; + var from = {}, to = {}; + + for (var i in obj){ + if (!this.elements[i]) continue; + + var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {}; + + for (var p in iProps){ + var parsed = this.prepare(this.elements[i], p, iProps[p]); + iFrom[p] = parsed.from; + iTo[p] = parsed.to; + } + } + + return this.parent(from, to); + } + +}); + + +/* +--- + +script: Fx.Accordion.js + +name: Fx.Accordion + +description: An Fx.Elements extension which allows you to easily create accordion type controls. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Element.Event + - /Fx.Elements + +provides: [Fx.Accordion] + +... +*/ + +Fx.Accordion = new Class({ + + Extends: Fx.Elements, + + options: {/* + onActive: function(toggler, section){}, + onBackground: function(toggler, section){},*/ + fixedHeight: false, + fixedWidth: false, + display: 0, + show: false, + height: true, + width: false, + opacity: true, + alwaysHide: false, + trigger: 'click', + initialDisplayFx: true, + resetHeight: true + }, + + initialize: function(){ + var defined = function(obj){ + return obj != null; + }; + + var params = Array.link(arguments, { + 'container': Type.isElement, //deprecated + 'options': Type.isObject, + 'togglers': defined, + 'elements': defined + }); + this.parent(params.elements, params.options); + + var options = this.options, + togglers = this.togglers = $$(params.togglers); + + this.previous = -1; + this.internalChain = new Chain(); + + if (options.alwaysHide) this.options.link = 'chain'; + + if (options.show || this.options.show === 0){ + options.display = false; + this.previous = options.show; + } + + if (options.start){ + options.display = false; + options.show = false; + } + + var effects = this.effects = {}; + + if (options.opacity) effects.opacity = 'fullOpacity'; + if (options.width) effects.width = options.fixedWidth ? 'fullWidth' : 'offsetWidth'; + if (options.height) effects.height = options.fixedHeight ? 'fullHeight' : 'scrollHeight'; + + for (var i = 0, l = togglers.length; i < l; i++) this.addSection(togglers[i], this.elements[i]); + + this.elements.each(function(el, i){ + if (options.show === i){ + this.fireEvent('active', [togglers[i], el]); + } else { + for (var fx in effects) el.setStyle(fx, 0); + } + }, this); + + if (options.display || options.display === 0 || options.initialDisplayFx === false){ + this.display(options.display, options.initialDisplayFx); + } + + if (options.fixedHeight !== false) options.resetHeight = false; + this.addEvent('complete', this.internalChain.callChain.bind(this.internalChain)); + }, + + addSection: function(toggler, element){ + toggler = document.id(toggler); + element = document.id(element); + this.togglers.include(toggler); + this.elements.include(element); + + var togglers = this.togglers, + options = this.options, + test = togglers.contains(toggler), + idx = togglers.indexOf(toggler), + displayer = this.display.pass(idx, this); + + toggler.store('accordion:display', displayer) + .addEvent(options.trigger, displayer); + + if (options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'}); + if (options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'}); + + element.fullOpacity = 1; + if (options.fixedWidth) element.fullWidth = options.fixedWidth; + if (options.fixedHeight) element.fullHeight = options.fixedHeight; + element.setStyle('overflow', 'hidden'); + + if (!test) for (var fx in this.effects){ + element.setStyle(fx, 0); + } + return this; + }, + + removeSection: function(toggler, displayIndex){ + var togglers = this.togglers, + idx = togglers.indexOf(toggler), + element = this.elements[idx]; + + var remover = function(){ + togglers.erase(toggler); + this.elements.erase(element); + this.detach(toggler); + }.bind(this); + + if (this.now == idx || displayIndex != null){ + this.display(displayIndex != null ? displayIndex : (idx - 1 >= 0 ? idx - 1 : 0)).chain(remover); + } else { + remover(); + } + return this; + }, + + detach: function(toggler){ + var remove = function(toggler){ + toggler.removeEvent(this.options.trigger, toggler.retrieve('accordion:display')); + }.bind(this); + + if (!toggler) this.togglers.each(remove); + else remove(toggler); + return this; + }, + + display: function(index, useFx){ + if (!this.check(index, useFx)) return this; + + var obj = {}, + elements = this.elements, + options = this.options, + effects = this.effects; + + if (useFx == null) useFx = true; + if (typeOf(index) == 'element') index = elements.indexOf(index); + if (index == this.previous && !options.alwaysHide) return this; + + if (options.resetHeight){ + var prev = elements[this.previous]; + if (prev && !this.selfHidden){ + for (var fx in effects) prev.setStyle(fx, prev[effects[fx]]); + } + } + + if ((this.timer && options.link == 'chain') || (index === this.previous && !options.alwaysHide)) return this; + + this.previous = index; + this.selfHidden = false; + + elements.each(function(el, i){ + obj[i] = {}; + var hide; + if (i != index){ + hide = true; + } else if (options.alwaysHide && ((el.offsetHeight > 0 && options.height) || el.offsetWidth > 0 && options.width)){ + hide = true; + this.selfHidden = true; + } + this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]); + for (var fx in effects) obj[i][fx] = hide ? 0 : el[effects[fx]]; + if (!useFx && !hide && options.resetHeight) obj[i].height = 'auto'; + }, this); + + this.internalChain.clearChain(); + this.internalChain.chain(function(){ + if (options.resetHeight && !this.selfHidden){ + var el = elements[index]; + if (el) el.setStyle('height', 'auto'); + } + }.bind(this)); + + return useFx ? this.start(obj) : this.set(obj).internalChain.callChain(); + } + +}); + + + + +/* +--- + +script: Fx.Move.js + +name: Fx.Move + +description: Defines Fx.Move, a class that works with Element.Position.js to transition an element from one location to another. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Fx.Morph + - /Element.Position + +provides: [Fx.Move] + +... +*/ + +Fx.Move = new Class({ + + Extends: Fx.Morph, + + options: { + relativeTo: document.body, + position: 'center', + edge: false, + offset: {x: 0, y: 0} + }, + + start: function(destination){ + var element = this.element, + topLeft = element.getStyles('top', 'left'); + if (topLeft.top == 'auto' || topLeft.left == 'auto'){ + element.setPosition(element.getPosition(element.getOffsetParent())); + } + return this.parent(element.position(Object.merge({}, this.options, destination, {returnPos: true}))); + } + +}); + +Element.Properties.move = { + + set: function(options){ + this.get('move').cancel().setOptions(options); + return this; + }, + + get: function(){ + var move = this.retrieve('move'); + if (!move){ + move = new Fx.Move(this, {link: 'cancel'}); + this.store('move', move); + } + return move; + } + +}; + +Element.implement({ + + move: function(options){ + this.get('move').start(options); + return this; + } + +}); + + +/* +--- + +script: Fx.Slide.js + +name: Fx.Slide + +description: Effect to slide an element in and out of view. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Fx + - Core/Element.Style + - /MooTools.More + +provides: [Fx.Slide] + +... +*/ + +Fx.Slide = new Class({ + + Extends: Fx, + + options: { + mode: 'vertical', + wrapper: false, + hideOverflow: true, + resetHeight: false + }, + + initialize: function(element, options){ + element = this.element = this.subject = document.id(element); + this.parent(options); + options = this.options; + + var wrapper = element.retrieve('wrapper'), + styles = element.getStyles('margin', 'position', 'overflow'); + + if (options.hideOverflow) styles = Object.append(styles, {overflow: 'hidden'}); + if (options.wrapper) wrapper = document.id(options.wrapper).setStyles(styles); + + if (!wrapper) wrapper = new Element('div', { + styles: styles + }).wraps(element); + + element.store('wrapper', wrapper).setStyle('margin', 0); + if (element.getStyle('overflow') == 'visible') element.setStyle('overflow', 'hidden'); + + this.now = []; + this.open = true; + this.wrapper = wrapper; + + this.addEvent('complete', function(){ + this.open = (wrapper['offset' + this.layout.capitalize()] != 0); + if (this.open && this.options.resetHeight) wrapper.setStyle('height', ''); + }, true); + }, + + vertical: function(){ + this.margin = 'margin-top'; + this.layout = 'height'; + this.offset = this.element.offsetHeight; + }, + + horizontal: function(){ + this.margin = 'margin-left'; + this.layout = 'width'; + this.offset = this.element.offsetWidth; + }, + + set: function(now){ + this.element.setStyle(this.margin, now[0]); + this.wrapper.setStyle(this.layout, now[1]); + return this; + }, + + compute: function(from, to, delta){ + return [0, 1].map(function(i){ + return Fx.compute(from[i], to[i], delta); + }); + }, + + start: function(how, mode){ + if (!this.check(how, mode)) return this; + this[mode || this.options.mode](); + + var margin = this.element.getStyle(this.margin).toInt(), + layout = this.wrapper.getStyle(this.layout).toInt(), + caseIn = [[margin, layout], [0, this.offset]], + caseOut = [[margin, layout], [-this.offset, 0]], + start; + + switch (how){ + case 'in': start = caseIn; break; + case 'out': start = caseOut; break; + case 'toggle': start = (layout == 0) ? caseIn : caseOut; + } + return this.parent(start[0], start[1]); + }, + + slideIn: function(mode){ + return this.start('in', mode); + }, + + slideOut: function(mode){ + return this.start('out', mode); + }, + + hide: function(mode){ + this[mode || this.options.mode](); + this.open = false; + return this.set([-this.offset, 0]); + }, + + show: function(mode){ + this[mode || this.options.mode](); + this.open = true; + return this.set([0, this.offset]); + }, + + toggle: function(mode){ + return this.start('toggle', mode); + } + +}); + +Element.Properties.slide = { + + set: function(options){ + this.get('slide').cancel().setOptions(options); + return this; + }, + + get: function(){ + var slide = this.retrieve('slide'); + if (!slide){ + slide = new Fx.Slide(this, {link: 'cancel'}); + this.store('slide', slide); + } + return slide; + } + +}; + +Element.implement({ + + slide: function(how, mode){ + how = how || 'toggle'; + var slide = this.get('slide'), toggle; + switch (how){ + case 'hide': slide.hide(mode); break; + case 'show': slide.show(mode); break; + case 'toggle': + var flag = this.retrieve('slide:flag', slide.open); + slide[flag ? 'slideOut' : 'slideIn'](mode); + this.store('slide:flag', !flag); + toggle = true; + break; + default: slide.start(how, mode); + } + if (!toggle) this.eliminate('slide:flag'); + return this; + } + +}); + + +/* +--- + +script: Fx.Scroll.js + +name: Fx.Scroll + +description: Effect to smoothly scroll any element, including the window. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Fx + - Core/Element.Event + - Core/Element.Dimensions + - /MooTools.More + +provides: [Fx.Scroll] + +... +*/ + +(function(){ + +Fx.Scroll = new Class({ + + Extends: Fx, + + options: { + offset: {x: 0, y: 0}, + wheelStops: true + }, + + initialize: function(element, options){ + this.element = this.subject = document.id(element); + this.parent(options); + + if (typeOf(this.element) != 'element') this.element = document.id(this.element.getDocument().body); + + if (this.options.wheelStops){ + var stopper = this.element, + cancel = this.cancel.pass(false, this); + this.addEvent('start', function(){ + stopper.addEvent('mousewheel', cancel); + }, true); + this.addEvent('complete', function(){ + stopper.removeEvent('mousewheel', cancel); + }, true); + } + }, + + set: function(){ + var now = Array.flatten(arguments); + if (Browser.firefox) now = [Math.round(now[0]), Math.round(now[1])]; // not needed anymore in newer firefox versions + this.element.scrollTo(now[0], now[1]); + return this; + }, + + compute: function(from, to, delta){ + return [0, 1].map(function(i){ + return Fx.compute(from[i], to[i], delta); + }); + }, + + start: function(x, y){ + if (!this.check(x, y)) return this; + var scroll = this.element.getScroll(); + return this.parent([scroll.x, scroll.y], [x, y]); + }, + + calculateScroll: function(x, y){ + var element = this.element, + scrollSize = element.getScrollSize(), + scroll = element.getScroll(), + size = element.getSize(), + offset = this.options.offset, + values = {x: x, y: y}; + + for (var z in values){ + if (!values[z] && values[z] !== 0) values[z] = scroll[z]; + if (typeOf(values[z]) != 'number') values[z] = scrollSize[z] - size[z]; + values[z] += offset[z]; + } + + return [values.x, values.y]; + }, + + toTop: function(){ + return this.start.apply(this, this.calculateScroll(false, 0)); + }, + + toLeft: function(){ + return this.start.apply(this, this.calculateScroll(0, false)); + }, + + toRight: function(){ + return this.start.apply(this, this.calculateScroll('right', false)); + }, + + toBottom: function(){ + return this.start.apply(this, this.calculateScroll(false, 'bottom')); + }, + + toElement: function(el, axes){ + axes = axes ? Array.from(axes) : ['x', 'y']; + var scroll = isBody(this.element) ? {x: 0, y: 0} : this.element.getScroll(); + var position = Object.map(document.id(el).getPosition(this.element), function(value, axis){ + return axes.contains(axis) ? value + scroll[axis] : false; + }); + return this.start.apply(this, this.calculateScroll(position.x, position.y)); + }, + + toElementEdge: function(el, axes, offset){ + axes = axes ? Array.from(axes) : ['x', 'y']; + el = document.id(el); + var to = {}, + position = el.getPosition(this.element), + size = el.getSize(), + scroll = this.element.getScroll(), + containerSize = this.element.getSize(), + edge = { + x: position.x + size.x, + y: position.y + size.y + }; + + ['x', 'y'].each(function(axis){ + if (axes.contains(axis)){ + if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis]; + if (position[axis] < scroll[axis]) to[axis] = position[axis]; + } + if (to[axis] == null) to[axis] = scroll[axis]; + if (offset && offset[axis]) to[axis] = to[axis] + offset[axis]; + }, this); + + if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y); + return this; + }, + + toElementCenter: function(el, axes, offset){ + axes = axes ? Array.from(axes) : ['x', 'y']; + el = document.id(el); + var to = {}, + position = el.getPosition(this.element), + size = el.getSize(), + scroll = this.element.getScroll(), + containerSize = this.element.getSize(); + + ['x', 'y'].each(function(axis){ + if (axes.contains(axis)){ + to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2; + } + if (to[axis] == null) to[axis] = scroll[axis]; + if (offset && offset[axis]) to[axis] = to[axis] + offset[axis]; + }, this); + + if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y); + return this; + } + +}); + + + +function isBody(element){ + return (/^(?:body|html)$/i).test(element.tagName); +} + +})(); + + +/* +--- + +script: Fx.SmoothScroll.js + +name: Fx.SmoothScroll + +description: Class for creating a smooth scrolling effect to all internal links on the page. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Slick.Finder + - /Fx.Scroll + +provides: [Fx.SmoothScroll] + +... +*/ + +Fx.SmoothScroll = new Class({ + + Extends: Fx.Scroll, + + options: { + axes: ['x', 'y'] + }, + + initialize: function(options, context){ + context = context || document; + this.doc = context.getDocument(); + this.parent(this.doc, options); + + var win = context.getWindow(), + location = win.location.href.match(/^[^#]*/)[0] + '#', + links = $$(this.options.links || this.doc.links); + + links.each(function(link){ + if (link.href.indexOf(location) != 0) return; + var anchor = link.href.substr(location.length); + if (anchor) this.useLink(link, anchor); + }, this); + + this.addEvent('complete', function(){ + win.location.hash = this.anchor; + this.element.scrollTo(this.to[0], this.to[1]); + }, true); + }, + + useLink: function(link, anchor){ + + link.addEvent('click', function(event){ + var el = document.id(anchor) || this.doc.getElement('a[name=' + anchor + ']'); + if (!el) return; + + event.preventDefault(); + this.toElement(el, this.options.axes).chain(function(){ + this.fireEvent('scrolledTo', [link, el]); + }.bind(this)); + + this.anchor = anchor; + + }.bind(this)); + + return this; + } +}); + + +/* +--- + +script: Fx.Sort.js + +name: Fx.Sort + +description: Defines Fx.Sort, a class that reorders lists with a transition. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element.Dimensions + - /Fx.Elements + - /Element.Measure + +provides: [Fx.Sort] + +... +*/ + +Fx.Sort = new Class({ + + Extends: Fx.Elements, + + options: { + mode: 'vertical' + }, + + initialize: function(elements, options){ + this.parent(elements, options); + this.elements.each(function(el){ + if (el.getStyle('position') == 'static') el.setStyle('position', 'relative'); + }); + this.setDefaultOrder(); + }, + + setDefaultOrder: function(){ + this.currentOrder = this.elements.map(function(el, index){ + return index; + }); + }, + + sort: function(){ + if (!this.check(arguments)) return this; + var newOrder = Array.flatten(arguments); + + var top = 0, + left = 0, + next = {}, + zero = {}, + vert = this.options.mode == 'vertical'; + + var current = this.elements.map(function(el, index){ + var size = el.getComputedSize({styles: ['border', 'padding', 'margin']}); + var val; + if (vert){ + val = { + top: top, + margin: size['margin-top'], + height: size.totalHeight + }; + top += val.height - size['margin-top']; + } else { + val = { + left: left, + margin: size['margin-left'], + width: size.totalWidth + }; + left += val.width; + } + var plane = vert ? 'top' : 'left'; + zero[index] = {}; + var start = el.getStyle(plane).toInt(); + zero[index][plane] = start || 0; + return val; + }, this); + + this.set(zero); + newOrder = newOrder.map(function(i){ return i.toInt(); }); + if (newOrder.length != this.elements.length){ + this.currentOrder.each(function(index){ + if (!newOrder.contains(index)) newOrder.push(index); + }); + if (newOrder.length > this.elements.length) + newOrder.splice(this.elements.length-1, newOrder.length - this.elements.length); + } + var margin = 0; + top = left = 0; + newOrder.each(function(item){ + var newPos = {}; + if (vert){ + newPos.top = top - current[item].top - margin; + top += current[item].height; + } else { + newPos.left = left - current[item].left; + left += current[item].width; + } + margin = margin + current[item].margin; + next[item]=newPos; + }, this); + var mapped = {}; + Array.clone(newOrder).sort().each(function(index){ + mapped[index] = next[index]; + }); + this.start(mapped); + this.currentOrder = newOrder; + + return this; + }, + + rearrangeDOM: function(newOrder){ + newOrder = newOrder || this.currentOrder; + var parent = this.elements[0].getParent(); + var rearranged = []; + this.elements.setStyle('opacity', 0); + //move each element and store the new default order + newOrder.each(function(index){ + rearranged.push(this.elements[index].inject(parent).setStyles({ + top: 0, + left: 0 + })); + }, this); + this.elements.setStyle('opacity', 1); + this.elements = $$(rearranged); + this.setDefaultOrder(); + return this; + }, + + getDefaultOrder: function(){ + return this.elements.map(function(el, index){ + return index; + }); + }, + + getCurrentOrder: function(){ + return this.currentOrder; + }, + + forward: function(){ + return this.sort(this.getDefaultOrder()); + }, + + backward: function(){ + return this.sort(this.getDefaultOrder().reverse()); + }, + + reverse: function(){ + return this.sort(this.currentOrder.reverse()); + }, + + sortByElements: function(elements){ + return this.sort(elements.map(function(el){ + return this.elements.indexOf(el); + }, this)); + }, + + swap: function(one, two){ + if (typeOf(one) == 'element') one = this.elements.indexOf(one); + if (typeOf(two) == 'element') two = this.elements.indexOf(two); + + var newOrder = Array.clone(this.currentOrder); + newOrder[this.currentOrder.indexOf(one)] = two; + newOrder[this.currentOrder.indexOf(two)] = one; + + return this.sort(newOrder); + } + +}); + + +/* +--- + +script: Drag.js + +name: Drag + +description: The base Drag Class. Can be used to drag and resize Elements using mouse events. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + +requires: + - Core/Events + - Core/Options + - Core/Element.Event + - Core/Element.Style + - Core/Element.Dimensions + - /MooTools.More + +provides: [Drag] +... + +*/ + +var Drag = new Class({ + + Implements: [Events, Options], + + options: {/* + onBeforeStart: function(thisElement){}, + onStart: function(thisElement, event){}, + onSnap: function(thisElement){}, + onDrag: function(thisElement, event){}, + onCancel: function(thisElement){}, + onComplete: function(thisElement, event){},*/ + snap: 6, + unit: 'px', + grid: false, + style: true, + limit: false, + handle: false, + invert: false, + preventDefault: false, + stopPropagation: false, + modifiers: {x: 'left', y: 'top'} + }, + + initialize: function(){ + var params = Array.link(arguments, { + 'options': Type.isObject, + 'element': function(obj){ + return obj != null; + } + }); + + this.element = document.id(params.element); + this.document = this.element.getDocument(); + this.setOptions(params.options || {}); + var htype = typeOf(this.options.handle); + this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element; + this.mouse = {'now': {}, 'pos': {}}; + this.value = {'start': {}, 'now': {}}; + + this.selection = (Browser.ie) ? 'selectstart' : 'mousedown'; + + + if (Browser.ie && !Drag.ondragstartFixed){ + document.ondragstart = Function.from(false); + Drag.ondragstartFixed = true; + } + + this.bound = { + start: this.start.bind(this), + check: this.check.bind(this), + drag: this.drag.bind(this), + stop: this.stop.bind(this), + cancel: this.cancel.bind(this), + eventStop: Function.from(false) + }; + this.attach(); + }, + + attach: function(){ + this.handles.addEvent('mousedown', this.bound.start); + return this; + }, + + detach: function(){ + this.handles.removeEvent('mousedown', this.bound.start); + return this; + }, + + start: function(event){ + var options = this.options; + + if (event.rightClick) return; + + if (options.preventDefault) event.preventDefault(); + if (options.stopPropagation) event.stopPropagation(); + this.mouse.start = event.page; + + this.fireEvent('beforeStart', this.element); + + var limit = options.limit; + this.limit = {x: [], y: []}; + + var z, coordinates; + for (z in options.modifiers){ + if (!options.modifiers[z]) continue; + + var style = this.element.getStyle(options.modifiers[z]); + + // Some browsers (IE and Opera) don't always return pixels. + if (style && !style.match(/px$/)){ + if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent()); + style = coordinates[options.modifiers[z]]; + } + + if (options.style) this.value.now[z] = (style || 0).toInt(); + else this.value.now[z] = this.element[options.modifiers[z]]; + + if (options.invert) this.value.now[z] *= -1; + + this.mouse.pos[z] = event.page[z] - this.value.now[z]; + + if (limit && limit[z]){ + var i = 2; + while (i--){ + var limitZI = limit[z][i]; + if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI; + } + } + } + + if (typeOf(this.options.grid) == 'number') this.options.grid = { + x: this.options.grid, + y: this.options.grid + }; + + var events = { + mousemove: this.bound.check, + mouseup: this.bound.cancel + }; + events[this.selection] = this.bound.eventStop; + this.document.addEvents(events); + }, + + check: function(event){ + if (this.options.preventDefault) event.preventDefault(); + var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2))); + if (distance > this.options.snap){ + this.cancel(); + this.document.addEvents({ + mousemove: this.bound.drag, + mouseup: this.bound.stop + }); + this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element); + } + }, + + drag: function(event){ + var options = this.options; + + if (options.preventDefault) event.preventDefault(); + this.mouse.now = event.page; + + for (var z in options.modifiers){ + if (!options.modifiers[z]) continue; + this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z]; + + if (options.invert) this.value.now[z] *= -1; + + if (options.limit && this.limit[z]){ + if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){ + this.value.now[z] = this.limit[z][1]; + } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){ + this.value.now[z] = this.limit[z][0]; + } + } + + if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]); + + if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit); + else this.element[options.modifiers[z]] = this.value.now[z]; + } + + this.fireEvent('drag', [this.element, event]); + }, + + cancel: function(event){ + this.document.removeEvents({ + mousemove: this.bound.check, + mouseup: this.bound.cancel + }); + if (event){ + this.document.removeEvent(this.selection, this.bound.eventStop); + this.fireEvent('cancel', this.element); + } + }, + + stop: function(event){ + var events = { + mousemove: this.bound.drag, + mouseup: this.bound.stop + }; + events[this.selection] = this.bound.eventStop; + this.document.removeEvents(events); + if (event) this.fireEvent('complete', [this.element, event]); + } + +}); + +Element.implement({ + + makeResizable: function(options){ + var drag = new Drag(this, Object.merge({ + modifiers: { + x: 'width', + y: 'height' + } + }, options)); + + this.store('resizer', drag); + return drag.addEvent('drag', function(){ + this.fireEvent('resize', drag); + }.bind(this)); + } + +}); + + +/* +--- + +script: Drag.Move.js + +name: Drag.Move + +description: A Drag extension that provides support for the constraining of draggables to containers and droppables. + +license: MIT-style license + +authors: + - Valerio Proietti + - Tom Occhinno + - Jan Kassens + - Aaron Newton + - Scott Kyle + +requires: + - Core/Element.Dimensions + - /Drag + +provides: [Drag.Move] + +... +*/ + +Drag.Move = new Class({ + + Extends: Drag, + + options: {/* + onEnter: function(thisElement, overed){}, + onLeave: function(thisElement, overed){}, + onDrop: function(thisElement, overed, event){},*/ + droppables: [], + container: false, + precalculate: false, + includeMargins: true, + checkDroppables: true + }, + + initialize: function(element, options){ + this.parent(element, options); + element = this.element; + + this.droppables = $$(this.options.droppables); + this.container = document.id(this.options.container); + + if (this.container && typeOf(this.container) != 'element') + this.container = document.id(this.container.getDocument().body); + + if (this.options.style){ + if (this.options.modifiers.x == 'left' && this.options.modifiers.y == 'top'){ + var parent = element.getOffsetParent(), + styles = element.getStyles('left', 'top'); + if (parent && (styles.left == 'auto' || styles.top == 'auto')){ + element.setPosition(element.getPosition(parent)); + } + } + + if (element.getStyle('position') == 'static') element.setStyle('position', 'absolute'); + } + + this.addEvent('start', this.checkDroppables, true); + this.overed = null; + }, + + start: function(event){ + if (this.container) this.options.limit = this.calculateLimit(); + + if (this.options.precalculate){ + this.positions = this.droppables.map(function(el){ + return el.getCoordinates(); + }); + } + + this.parent(event); + }, + + calculateLimit: function(){ + var element = this.element, + container = this.container, + + offsetParent = document.id(element.getOffsetParent()) || document.body, + containerCoordinates = container.getCoordinates(offsetParent), + elementMargin = {}, + elementBorder = {}, + containerMargin = {}, + containerBorder = {}, + offsetParentPadding = {}; + + ['top', 'right', 'bottom', 'left'].each(function(pad){ + elementMargin[pad] = element.getStyle('margin-' + pad).toInt(); + elementBorder[pad] = element.getStyle('border-' + pad).toInt(); + containerMargin[pad] = container.getStyle('margin-' + pad).toInt(); + containerBorder[pad] = container.getStyle('border-' + pad).toInt(); + offsetParentPadding[pad] = offsetParent.getStyle('padding-' + pad).toInt(); + }, this); + + var width = element.offsetWidth + elementMargin.left + elementMargin.right, + height = element.offsetHeight + elementMargin.top + elementMargin.bottom, + left = 0, + top = 0, + right = containerCoordinates.right - containerBorder.right - width, + bottom = containerCoordinates.bottom - containerBorder.bottom - height; + + if (this.options.includeMargins){ + left += elementMargin.left; + top += elementMargin.top; + } else { + right += elementMargin.right; + bottom += elementMargin.bottom; + } + + if (element.getStyle('position') == 'relative'){ + var coords = element.getCoordinates(offsetParent); + coords.left -= element.getStyle('left').toInt(); + coords.top -= element.getStyle('top').toInt(); + + left -= coords.left; + top -= coords.top; + if (container.getStyle('position') != 'relative'){ + left += containerBorder.left; + top += containerBorder.top; + } + right += elementMargin.left - coords.left; + bottom += elementMargin.top - coords.top; + + if (container != offsetParent){ + left += containerMargin.left + offsetParentPadding.left; + top += ((Browser.ie6 || Browser.ie7) ? 0 : containerMargin.top) + offsetParentPadding.top; + } + } else { + left -= elementMargin.left; + top -= elementMargin.top; + if (container != offsetParent){ + left += containerCoordinates.left + containerBorder.left; + top += containerCoordinates.top + containerBorder.top; + } + } + + return { + x: [left, right], + y: [top, bottom] + }; + }, + + getDroppableCoordinates: function(element){ + var position = element.getCoordinates(); + if (element.getStyle('position') == 'fixed'){ + var scroll = window.getScroll(); + position.left += scroll.x; + position.right += scroll.x; + position.top += scroll.y; + position.bottom += scroll.y; + } + return position; + }, + + checkDroppables: function(){ + var overed = this.droppables.filter(function(el, i){ + el = this.positions ? this.positions[i] : this.getDroppableCoordinates(el); + var now = this.mouse.now; + return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top); + }, this).getLast(); + + if (this.overed != overed){ + if (this.overed) this.fireEvent('leave', [this.element, this.overed]); + if (overed) this.fireEvent('enter', [this.element, overed]); + this.overed = overed; + } + }, + + drag: function(event){ + this.parent(event); + if (this.options.checkDroppables && this.droppables.length) this.checkDroppables(); + }, + + stop: function(event){ + this.checkDroppables(); + this.fireEvent('drop', [this.element, this.overed, event]); + this.overed = null; + return this.parent(event); + } + +}); + +Element.implement({ + + makeDraggable: function(options){ + var drag = new Drag.Move(this, options); + this.store('dragger', drag); + return drag; + } + +}); + + +/* +--- + +script: Slider.js + +name: Slider + +description: Class for creating horizontal and vertical slider controls. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Element.Dimensions + - /Class.Binds + - /Drag + - /Element.Measure + +provides: [Slider] + +... +*/ + +var Slider = new Class({ + + Implements: [Events, Options], + + Binds: ['clickedElement', 'draggedKnob', 'scrolledElement'], + + options: {/* + onTick: function(intPosition){}, + onChange: function(intStep){}, + onComplete: function(strStep){},*/ + onTick: function(position){ + this.setKnobPosition(position); + }, + initialStep: 0, + snap: false, + offset: 0, + range: false, + wheel: false, + steps: 100, + mode: 'horizontal' + }, + + initialize: function(element, knob, options){ + this.setOptions(options); + options = this.options; + this.element = document.id(element); + knob = this.knob = document.id(knob); + this.previousChange = this.previousEnd = this.step = -1; + + var limit = {}, + modifiers = {x: false, y: false}; + + switch (options.mode){ + case 'vertical': + this.axis = 'y'; + this.property = 'top'; + this.offset = 'offsetHeight'; + break; + case 'horizontal': + this.axis = 'x'; + this.property = 'left'; + this.offset = 'offsetWidth'; + } + + this.setSliderDimensions(); + this.setRange(options.range); + + if (knob.getStyle('position') == 'static') knob.setStyle('position', 'relative'); + knob.setStyle(this.property, -options.offset); + modifiers[this.axis] = this.property; + limit[this.axis] = [-options.offset, this.full - options.offset]; + + var dragOptions = { + snap: 0, + limit: limit, + modifiers: modifiers, + onDrag: this.draggedKnob, + onStart: this.draggedKnob, + onBeforeStart: (function(){ + this.isDragging = true; + }).bind(this), + onCancel: function(){ + this.isDragging = false; + }.bind(this), + onComplete: function(){ + this.isDragging = false; + this.draggedKnob(); + this.end(); + }.bind(this) + }; + if (options.snap) this.setSnap(dragOptions); + + this.drag = new Drag(knob, dragOptions); + this.attach(); + if (options.initialStep != null) this.set(options.initialStep); + }, + + attach: function(){ + this.element.addEvent('mousedown', this.clickedElement); + if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement); + this.drag.attach(); + return this; + }, + + detach: function(){ + this.element.removeEvent('mousedown', this.clickedElement) + .removeEvent('mousewheel', this.scrolledElement); + this.drag.detach(); + return this; + }, + + autosize: function(){ + this.setSliderDimensions() + .setKnobPosition(this.toPosition(this.step)); + this.drag.options.limit[this.axis] = [-this.options.offset, this.full - this.options.offset]; + if (this.options.snap) this.setSnap(); + return this; + }, + + setSnap: function(options){ + if (!options) options = this.drag.options; + options.grid = Math.ceil(this.stepWidth); + options.limit[this.axis][1] = this.full; + return this; + }, + + setKnobPosition: function(position){ + if (this.options.snap) position = this.toPosition(this.step); + this.knob.setStyle(this.property, position); + return this; + }, + + setSliderDimensions: function(){ + this.full = this.element.measure(function(){ + this.half = this.knob[this.offset] / 2; + return this.element[this.offset] - this.knob[this.offset] + (this.options.offset * 2); + }.bind(this)); + return this; + }, + + set: function(step){ + if (!((this.range > 0) ^ (step < this.min))) step = this.min; + if (!((this.range > 0) ^ (step > this.max))) step = this.max; + + this.step = Math.round(step); + return this.checkStep() + .fireEvent('tick', this.toPosition(this.step)) + .end(); + }, + + setRange: function(range, pos){ + this.min = Array.pick([range[0], 0]); + this.max = Array.pick([range[1], this.options.steps]); + this.range = this.max - this.min; + this.steps = this.options.steps || this.full; + this.stepSize = Math.abs(this.range) / this.steps; + this.stepWidth = this.stepSize * this.full / Math.abs(this.range); + if (range) this.set(Array.pick([pos, this.step]).floor(this.min).max(this.max)); + return this; + }, + + clickedElement: function(event){ + if (this.isDragging || event.target == this.knob) return; + + var dir = this.range < 0 ? -1 : 1, + position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half; + + position = position.limit(-this.options.offset, this.full - this.options.offset); + + this.step = Math.round(this.min + dir * this.toStep(position)); + + this.checkStep() + .fireEvent('tick', position) + .end(); + }, + + scrolledElement: function(event){ + var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0); + this.set(this.step + (mode ? -1 : 1) * this.stepSize); + event.stop(); + }, + + draggedKnob: function(){ + var dir = this.range < 0 ? -1 : 1, + position = this.drag.value.now[this.axis]; + + position = position.limit(-this.options.offset, this.full -this.options.offset); + + this.step = Math.round(this.min + dir * this.toStep(position)); + this.checkStep(); + }, + + checkStep: function(){ + var step = this.step; + if (this.previousChange != step){ + this.previousChange = step; + this.fireEvent('change', step); + } + return this; + }, + + end: function(){ + var step = this.step; + if (this.previousEnd !== step){ + this.previousEnd = step; + this.fireEvent('complete', step + ''); + } + return this; + }, + + toStep: function(position){ + var step = (position + this.options.offset) * this.stepSize / this.full * this.steps; + return this.options.steps ? Math.round(step -= step % this.stepSize) : step; + }, + + toPosition: function(step){ + return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset; + } + +}); + + +/* +--- + +script: Sortables.js + +name: Sortables + +description: Class for creating a drag and drop sorting interface for lists of items. + +license: MIT-style license + +authors: + - Tom Occhino + +requires: + - Core/Fx.Morph + - /Drag.Move + +provides: [Sortables] + +... +*/ + +var Sortables = new Class({ + + Implements: [Events, Options], + + options: {/* + onSort: function(element, clone){}, + onStart: function(element, clone){}, + onComplete: function(element){},*/ + opacity: 1, + clone: false, + revert: false, + handle: false, + dragOptions: {} + }, + + initialize: function(lists, options){ + this.setOptions(options); + + this.elements = []; + this.lists = []; + this.idle = true; + + this.addLists($$(document.id(lists) || lists)); + + if (!this.options.clone) this.options.revert = false; + if (this.options.revert) this.effect = new Fx.Morph(null, Object.merge({ + duration: 250, + link: 'cancel' + }, this.options.revert)); + }, + + attach: function(){ + this.addLists(this.lists); + return this; + }, + + detach: function(){ + this.lists = this.removeLists(this.lists); + return this; + }, + + addItems: function(){ + Array.flatten(arguments).each(function(element){ + this.elements.push(element); + var start = element.retrieve('sortables:start', function(event){ + this.start.call(this, event, element); + }.bind(this)); + (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start); + }, this); + return this; + }, + + addLists: function(){ + Array.flatten(arguments).each(function(list){ + this.lists.include(list); + this.addItems(list.getChildren()); + }, this); + return this; + }, + + removeItems: function(){ + return $$(Array.flatten(arguments).map(function(element){ + this.elements.erase(element); + var start = element.retrieve('sortables:start'); + (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start); + + return element; + }, this)); + }, + + removeLists: function(){ + return $$(Array.flatten(arguments).map(function(list){ + this.lists.erase(list); + this.removeItems(list.getChildren()); + + return list; + }, this)); + }, + + getClone: function(event, element){ + if (!this.options.clone) return new Element(element.tagName).inject(document.body); + if (typeOf(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list); + var clone = element.clone(true).setStyles({ + margin: 0, + position: 'absolute', + visibility: 'hidden', + width: element.getStyle('width') + }).addEvent('mousedown', function(event){ + element.fireEvent('mousedown', event); + }); + //prevent the duplicated radio inputs from unchecking the real one + if (clone.get('html').test('radio')){ + clone.getElements('input[type=radio]').each(function(input, i){ + input.set('name', 'clone_' + i); + if (input.get('checked')) element.getElements('input[type=radio]')[i].set('checked', true); + }); + } + + return clone.inject(this.list).setPosition(element.getPosition(element.getOffsetParent())); + }, + + getDroppables: function(){ + var droppables = this.list.getChildren().erase(this.clone).erase(this.element); + if (!this.options.constrain) droppables.append(this.lists).erase(this.list); + return droppables; + }, + + insert: function(dragging, element){ + var where = 'inside'; + if (this.lists.contains(element)){ + this.list = element; + this.drag.droppables = this.getDroppables(); + } else { + where = this.element.getAllPrevious().contains(element) ? 'before' : 'after'; + } + this.element.inject(element, where); + this.fireEvent('sort', [this.element, this.clone]); + }, + + start: function(event, element){ + if ( + !this.idle || + event.rightClick || + ['button', 'input', 'a'].contains(event.target.get('tag')) + ) return; + + this.idle = false; + this.element = element; + this.opacity = element.get('opacity'); + this.list = element.getParent(); + this.clone = this.getClone(event, element); + + this.drag = new Drag.Move(this.clone, Object.merge({ + + droppables: this.getDroppables() + }, this.options.dragOptions)).addEvents({ + onSnap: function(){ + event.stop(); + this.clone.setStyle('visibility', 'visible'); + this.element.set('opacity', this.options.opacity || 0); + this.fireEvent('start', [this.element, this.clone]); + }.bind(this), + onEnter: this.insert.bind(this), + onCancel: this.end.bind(this), + onComplete: this.end.bind(this) + }); + + this.clone.inject(this.element, 'before'); + this.drag.start(event); + }, + + end: function(){ + this.drag.detach(); + this.element.set('opacity', this.opacity); + if (this.effect){ + var dim = this.element.getStyles('width', 'height'), + clone = this.clone, + pos = clone.computePosition(this.element.getPosition(this.clone.getOffsetParent())); + + var destroy = function(){ + this.removeEvent('cancel', destroy); + clone.destroy(); + }; + + this.effect.element = clone; + this.effect.start({ + top: pos.top, + left: pos.left, + width: dim.width, + height: dim.height, + opacity: 0.25 + }).addEvent('cancel', destroy).chain(destroy); + } else { + this.clone.destroy(); + } + this.reset(); + }, + + reset: function(){ + this.idle = true; + this.fireEvent('complete', this.element); + }, + + serialize: function(){ + var params = Array.link(arguments, { + modifier: Type.isFunction, + index: function(obj){ + return obj != null; + } + }); + var serial = this.lists.map(function(list){ + return list.getChildren().map(params.modifier || function(element){ + return element.get('id'); + }, this); + }, this); + + var index = params.index; + if (this.lists.length == 1) index = 0; + return (index || index === 0) && index >= 0 && index < this.lists.length ? serial[index] : serial; + } + +}); + + +/* +--- + +script: Request.JSONP.js + +name: Request.JSONP + +description: Defines Request.JSONP, a class for cross domain javascript via script injection. + +license: MIT-style license + +authors: + - Aaron Newton + - Guillermo Rauch + - Arian Stolwijk + +requires: + - Core/Element + - Core/Request + - MooTools.More + +provides: [Request.JSONP] + +... +*/ + +Request.JSONP = new Class({ + + Implements: [Chain, Events, Options], + + options: {/* + onRequest: function(src, scriptElement){}, + onComplete: function(data){}, + onSuccess: function(data){}, + onCancel: function(){}, + onTimeout: function(){}, + onError: function(){}, */ + onRequest: function(src){ + if (this.options.log && window.console && console.log){ + console.log('JSONP retrieving script with url:' + src); + } + }, + onError: function(src){ + if (this.options.log && window.console && console.warn){ + console.warn('JSONP '+ src +' will fail in Internet Explorer, which enforces a 2083 bytes length limit on URIs'); + } + }, + url: '', + callbackKey: 'callback', + injectScript: document.head, + data: '', + link: 'ignore', + timeout: 0, + log: false + }, + + initialize: function(options){ + this.setOptions(options); + }, + + send: function(options){ + if (!Request.prototype.check.call(this, options)) return this; + this.running = true; + + var type = typeOf(options); + if (type == 'string' || type == 'element') options = {data: options}; + options = Object.merge(this.options, options || {}); + + var data = options.data; + switch (typeOf(data)){ + case 'element': data = document.id(data).toQueryString(); break; + case 'object': case 'hash': data = Object.toQueryString(data); + } + + var index = this.index = Request.JSONP.counter++; + + var src = options.url + + (options.url.test('\\?') ? '&' :'?') + + (options.callbackKey) + + '=Request.JSONP.request_map.request_'+ index + + (data ? '&' + data : ''); + + if (src.length > 2083) this.fireEvent('error', src); + + Request.JSONP.request_map['request_' + index] = function(){ + this.success(arguments, index); + }.bind(this); + + var script = this.getScript(src).inject(options.injectScript); + this.fireEvent('request', [src, script]); + + if (options.timeout) this.timeout.delay(options.timeout, this); + + return this; + }, + + getScript: function(src){ + if (!this.script) this.script = new Element('script', { + type: 'text/javascript', + async: true, + src: src + }); + return this.script; + }, + + success: function(args, index){ + if (!this.running) return; + this.clear() + .fireEvent('complete', args).fireEvent('success', args) + .callChain(); + }, + + cancel: function(){ + if (this.running) this.clear().fireEvent('cancel'); + return this; + }, + + isRunning: function(){ + return !!this.running; + }, + + clear: function(){ + this.running = false; + if (this.script){ + this.script.destroy(); + this.script = null; + } + return this; + }, + + timeout: function(){ + if (this.running){ + this.running = false; + this.fireEvent('timeout', [this.script.get('src'), this.script]).fireEvent('failure').cancel(); + } + return this; + } + +}); + +Request.JSONP.counter = 0; +Request.JSONP.request_map = {}; + + +/* +--- + +script: Request.Queue.js + +name: Request.Queue + +description: Controls several instances of Request and its variants to run only one request at a time. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Element + - Core/Request + - /Class.Binds + +provides: [Request.Queue] + +... +*/ + +Request.Queue = new Class({ + + Implements: [Options, Events], + + Binds: ['attach', 'request', 'complete', 'cancel', 'success', 'failure', 'exception'], + + options: {/* + onRequest: function(argsPassedToOnRequest){}, + onSuccess: function(argsPassedToOnSuccess){}, + onComplete: function(argsPassedToOnComplete){}, + onCancel: function(argsPassedToOnCancel){}, + onException: function(argsPassedToOnException){}, + onFailure: function(argsPassedToOnFailure){}, + onEnd: function(){}, + */ + stopOnFailure: true, + autoAdvance: true, + concurrent: 1, + requests: {} + }, + + initialize: function(options){ + var requests; + if (options){ + requests = options.requests; + delete options.requests; + } + this.setOptions(options); + this.requests = {}; + this.queue = []; + this.reqBinders = {}; + + if (requests) this.addRequests(requests); + }, + + addRequest: function(name, request){ + this.requests[name] = request; + this.attach(name, request); + return this; + }, + + addRequests: function(obj){ + Object.each(obj, function(req, name){ + this.addRequest(name, req); + }, this); + return this; + }, + + getName: function(req){ + return Object.keyOf(this.requests, req); + }, + + attach: function(name, req){ + if (req._groupSend) return this; + ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){ + if (!this.reqBinders[name]) this.reqBinders[name] = {}; + this.reqBinders[name][evt] = function(){ + this['on' + evt.capitalize()].apply(this, [name, req].append(arguments)); + }.bind(this); + req.addEvent(evt, this.reqBinders[name][evt]); + }, this); + req._groupSend = req.send; + req.send = function(options){ + this.send(name, options); + return req; + }.bind(this); + return this; + }, + + removeRequest: function(req){ + var name = typeOf(req) == 'object' ? this.getName(req) : req; + if (!name && typeOf(name) != 'string') return this; + req = this.requests[name]; + if (!req) return this; + ['request', 'complete', 'cancel', 'success', 'failure', 'exception'].each(function(evt){ + req.removeEvent(evt, this.reqBinders[name][evt]); + }, this); + req.send = req._groupSend; + delete req._groupSend; + return this; + }, + + getRunning: function(){ + return Object.filter(this.requests, function(r){ + return r.running; + }); + }, + + isRunning: function(){ + return !!(Object.keys(this.getRunning()).length); + }, + + send: function(name, options){ + var q = function(){ + this.requests[name]._groupSend(options); + this.queue.erase(q); + }.bind(this); + + q.name = name; + if (Object.keys(this.getRunning()).length >= this.options.concurrent || (this.error && this.options.stopOnFailure)) this.queue.push(q); + else q(); + return this; + }, + + hasNext: function(name){ + return (!name) ? !!this.queue.length : !!this.queue.filter(function(q){ return q.name == name; }).length; + }, + + resume: function(){ + this.error = false; + (this.options.concurrent - Object.keys(this.getRunning()).length).times(this.runNext, this); + return this; + }, + + runNext: function(name){ + if (!this.queue.length) return this; + if (!name){ + this.queue[0](); + } else { + var found; + this.queue.each(function(q){ + if (!found && q.name == name){ + found = true; + q(); + } + }); + } + return this; + }, + + runAll: function(){ + this.queue.each(function(q){ + q(); + }); + return this; + }, + + clear: function(name){ + if (!name){ + this.queue.empty(); + } else { + this.queue = this.queue.map(function(q){ + if (q.name != name) return q; + else return false; + }).filter(function(q){ + return q; + }); + } + return this; + }, + + cancel: function(name){ + this.requests[name].cancel(); + return this; + }, + + onRequest: function(){ + this.fireEvent('request', arguments); + }, + + onComplete: function(){ + this.fireEvent('complete', arguments); + if (!this.queue.length) this.fireEvent('end'); + }, + + onCancel: function(){ + if (this.options.autoAdvance && !this.error) this.runNext(); + this.fireEvent('cancel', arguments); + }, + + onSuccess: function(){ + if (this.options.autoAdvance && !this.error) this.runNext(); + this.fireEvent('success', arguments); + }, + + onFailure: function(){ + this.error = true; + if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext(); + this.fireEvent('failure', arguments); + }, + + onException: function(){ + this.error = true; + if (!this.options.stopOnFailure && this.options.autoAdvance) this.runNext(); + this.fireEvent('exception', arguments); + } + +}); + + +/* +--- + +script: Request.Periodical.js + +name: Request.Periodical + +description: Requests the same URL to pull data from a server but increases the intervals if no data is returned to reduce the load + +license: MIT-style license + +authors: + - Christoph Pojer + +requires: + - Core/Request + - /MooTools.More + +provides: [Request.Periodical] + +... +*/ + +Request.implement({ + + options: { + initialDelay: 5000, + delay: 5000, + limit: 60000 + }, + + startTimer: function(data){ + var fn = function(){ + if (!this.running) this.send({data: data}); + }; + this.lastDelay = this.options.initialDelay; + this.timer = fn.delay(this.lastDelay, this); + this.completeCheck = function(response){ + clearTimeout(this.timer); + this.lastDelay = (response) ? this.options.delay : (this.lastDelay + this.options.delay).min(this.options.limit); + this.timer = fn.delay(this.lastDelay, this); + }; + return this.addEvent('complete', this.completeCheck); + }, + + stopTimer: function(){ + clearTimeout(this.timer); + return this.removeEvent('complete', this.completeCheck); + } + +}); + + +/* +--- + +script: Assets.js + +name: Assets + +description: Provides methods to dynamically load JavaScript, CSS, and Image files into the document. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Element.Event + - /MooTools.More + +provides: [Assets] + +... +*/ + +var Asset = { + + javascript: function(source, properties){ + if (!properties) properties = {}; + + var script = new Element('script', {src: source, type: 'text/javascript'}), + doc = properties.document || document, + loaded = 0, + loadEvent = properties.onload || properties.onLoad; + + var load = loadEvent ? function(){ // make sure we only call the event once + if (++loaded == 1) loadEvent.call(this); + } : function(){}; + + delete properties.onload; + delete properties.onLoad; + delete properties.document; + + return script.addEvents({ + load: load, + readystatechange: function(){ + if (['loaded', 'complete'].contains(this.readyState)) load.call(this); + } + }).set(properties).inject(doc.head); + }, + + css: function(source, properties){ + if (!properties) properties = {}; + + var link = new Element('link', { + rel: 'stylesheet', + media: 'screen', + type: 'text/css', + href: source + }); + + var load = properties.onload || properties.onLoad, + doc = properties.document || document; + + delete properties.onload; + delete properties.onLoad; + delete properties.document; + + if (load) link.addEvent('load', load); + return link.set(properties).inject(doc.head); + }, + + image: function(source, properties){ + if (!properties) properties = {}; + + var image = new Image(), + element = document.id(image) || new Element('img'); + + ['load', 'abort', 'error'].each(function(name){ + var type = 'on' + name, + cap = 'on' + name.capitalize(), + event = properties[type] || properties[cap] || function(){}; + + delete properties[cap]; + delete properties[type]; + + image[type] = function(){ + if (!image) return; + if (!element.parentNode){ + element.width = image.width; + element.height = image.height; + } + image = image.onload = image.onabort = image.onerror = null; + event.delay(1, element, element); + element.fireEvent(name, element, 1); + }; + }); + + image.src = element.src = source; + if (image && image.complete) image.onload.delay(1); + return element.set(properties); + }, + + images: function(sources, options){ + sources = Array.from(sources); + + var fn = function(){}, + counter = 0; + + options = Object.merge({ + onComplete: fn, + onProgress: fn, + onError: fn, + properties: {} + }, options); + + return new Elements(sources.map(function(source, index){ + return Asset.image(source, Object.append(options.properties, { + onload: function(){ + counter++; + options.onProgress.call(this, counter, index, source); + if (counter == sources.length) options.onComplete(); + }, + onerror: function(){ + counter++; + options.onError.call(this, counter, index, source); + if (counter == sources.length) options.onComplete(); + } + })); + })); + } + +}; + + +/* +--- + +script: Color.js + +name: Color + +description: Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Array + - Core/String + - Core/Number + - Core/Hash + - Core/Function + - MooTools.More + +provides: [Color] + +... +*/ + +(function(){ + +var Color = this.Color = new Type('Color', function(color, type){ + if (arguments.length >= 3){ + type = 'rgb'; color = Array.slice(arguments, 0, 3); + } else if (typeof color == 'string'){ + if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true); + else if (color.match(/hsb/)) color = color.hsbToRgb(); + else color = color.hexToRgb(true); + } + type = type || 'rgb'; + switch (type){ + case 'hsb': + var old = color; + color = color.hsbToRgb(); + color.hsb = old; + break; + case 'hex': color = color.hexToRgb(true); break; + } + color.rgb = color.slice(0, 3); + color.hsb = color.hsb || color.rgbToHsb(); + color.hex = color.rgbToHex(); + return Object.append(color, this); +}); + +Color.implement({ + + mix: function(){ + var colors = Array.slice(arguments); + var alpha = (typeOf(colors.getLast()) == 'number') ? colors.pop() : 50; + var rgb = this.slice(); + colors.each(function(color){ + color = new Color(color); + for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha)); + }); + return new Color(rgb, 'rgb'); + }, + + invert: function(){ + return new Color(this.map(function(value){ + return 255 - value; + })); + }, + + setHue: function(value){ + return new Color([value, this.hsb[1], this.hsb[2]], 'hsb'); + }, + + setSaturation: function(percent){ + return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb'); + }, + + setBrightness: function(percent){ + return new Color([this.hsb[0], this.hsb[1], percent], 'hsb'); + } + +}); + +this.$RGB = function(r, g, b){ + return new Color([r, g, b], 'rgb'); +}; + +this.$HSB = function(h, s, b){ + return new Color([h, s, b], 'hsb'); +}; + +this.$HEX = function(hex){ + return new Color(hex, 'hex'); +}; + +Array.implement({ + + rgbToHsb: function(){ + var red = this[0], + green = this[1], + blue = this[2], + hue = 0; + var max = Math.max(red, green, blue), + min = Math.min(red, green, blue); + var delta = max - min; + var brightness = max / 255, + saturation = (max != 0) ? delta / max : 0; + if (saturation != 0){ + var rr = (max - red) / delta; + var gr = (max - green) / delta; + var br = (max - blue) / delta; + if (red == max) hue = br - gr; + else if (green == max) hue = 2 + rr - br; + else hue = 4 + gr - rr; + hue /= 6; + if (hue < 0) hue++; + } + return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)]; + }, + + hsbToRgb: function(){ + var br = Math.round(this[2] / 100 * 255); + if (this[1] == 0){ + return [br, br, br]; + } else { + var hue = this[0] % 360; + var f = hue % 60; + var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255); + var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255); + var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255); + switch (Math.floor(hue / 60)){ + case 0: return [br, t, p]; + case 1: return [q, br, p]; + case 2: return [p, br, t]; + case 3: return [p, q, br]; + case 4: return [t, p, br]; + case 5: return [br, p, q]; + } + } + return false; + } + +}); + +String.implement({ + + rgbToHsb: function(){ + var rgb = this.match(/\d{1,3}/g); + return (rgb) ? rgb.rgbToHsb() : null; + }, + + hsbToRgb: function(){ + var hsb = this.match(/\d{1,3}/g); + return (hsb) ? hsb.hsbToRgb() : null; + } + +}); + +})(); + + + +/* +--- + +script: Group.js + +name: Group + +description: Class for monitoring collections of events + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Events + - /MooTools.More + +provides: [Group] + +... +*/ + +(function(){ + +this.Group = new Class({ + + initialize: function(){ + this.instances = Array.flatten(arguments); + this.events = {}; + this.checker = {}; + }, + + addEvent: function(type, fn){ + this.checker[type] = this.checker[type] || {}; + this.events[type] = this.events[type] || []; + if (this.events[type].contains(fn)) return false; + else this.events[type].push(fn); + this.instances.each(function(instance, i){ + instance.addEvent(type, this.check.pass([type, instance, i], this)); + }, this); + return this; + }, + + check: function(type, instance, i){ + this.checker[type][i] = true; + var every = this.instances.every(function(current, j){ + return this.checker[type][j] || false; + }, this); + if (!every) return; + this.checker[type] = {}; + this.events[type].each(function(event){ + event.call(this, this.instances, instance); + }, this); + } + +}); + +})(); + + + +/* +--- + +script: Hash.Cookie.js + +name: Hash.Cookie + +description: Class for creating, reading, and deleting Cookies in JSON format. + +license: MIT-style license + +authors: + - Valerio Proietti + - Aaron Newton + +requires: + - Core/Cookie + - Core/JSON + - /MooTools.More + - /Hash + +provides: [Hash.Cookie] + +... +*/ + +Hash.Cookie = new Class({ + + Extends: Cookie, + + options: { + autoSave: true + }, + + initialize: function(name, options){ + this.parent(name, options); + this.load(); + }, + + save: function(){ + var value = JSON.encode(this.hash); + if (!value || value.length > 4096) return false; //cookie would be truncated! + if (value == '{}') this.dispose(); + else this.write(value); + return true; + }, + + load: function(){ + this.hash = new Hash(JSON.decode(this.read(), true)); + return this; + } + +}); + +Hash.each(Hash.prototype, function(method, name){ + if (typeof method == 'function') Hash.Cookie.implement(name, function(){ + var value = method.apply(this.hash, arguments); + if (this.options.autoSave) this.save(); + return value; + }); +}); + + +/* +--- +name: Table +description: LUA-Style table implementation. +license: MIT-style license +authors: + - Valerio Proietti +requires: [Core/Array] +provides: [Table] +... +*/ + +(function(){ + +var Table = this.Table = function(){ + + this.length = 0; + var keys = [], + values = []; + + this.set = function(key, value){ + var index = keys.indexOf(key); + if (index == -1){ + var length = keys.length; + keys[length] = key; + values[length] = value; + this.length++; + } else { + values[index] = value; + } + return this; + }; + + this.get = function(key){ + var index = keys.indexOf(key); + return (index == -1) ? null : values[index]; + }; + + this.erase = function(key){ + var index = keys.indexOf(key); + if (index != -1){ + this.length--; + keys.splice(index, 1); + return values.splice(index, 1)[0]; + } + return null; + }; + + this.each = this.forEach = function(fn, bind){ + for (var i = 0, l = this.length; i < l; i++) fn.call(bind, keys[i], values[i], this); + }; + +}; + +if (this.Type) new Type('Table', Table); + +})(); + + +/* +--- + +script: HtmlTable.js + +name: HtmlTable + +description: Builds table elements with methods to add rows. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - Core/Options + - Core/Events + - /Class.Occlude + +provides: [HtmlTable] + +... +*/ + +var HtmlTable = new Class({ + + Implements: [Options, Events, Class.Occlude], + + options: { + properties: { + cellpadding: 0, + cellspacing: 0, + border: 0 + }, + rows: [], + headers: [], + footers: [] + }, + + property: 'HtmlTable', + + initialize: function(){ + var params = Array.link(arguments, {options: Type.isObject, table: Type.isElement, id: Type.isString}); + this.setOptions(params.options); + if (!params.table && params.id) params.table = document.id(params.id); + this.element = params.table || new Element('table', this.options.properties); + if (this.occlude()) return this.occluded; + this.build(); + }, + + build: function(){ + this.element.store('HtmlTable', this); + + this.body = document.id(this.element.tBodies[0]) || new Element('tbody').inject(this.element); + $$(this.body.rows); + + if (this.options.headers.length) this.setHeaders(this.options.headers); + else this.thead = document.id(this.element.tHead); + + if (this.thead) this.head = this.getHead(); + if (this.options.footers.length) this.setFooters(this.options.footers); + + this.tfoot = document.id(this.element.tFoot); + if (this.tfoot) this.foot = document.id(this.tfoot.rows[0]); + + this.options.rows.each(function(row){ + this.push(row); + }, this); + }, + + toElement: function(){ + return this.element; + }, + + empty: function(){ + this.body.empty(); + return this; + }, + + set: function(what, items){ + var target = (what == 'headers') ? 'tHead' : 'tFoot', + lower = target.toLowerCase(); + + this[lower] = (document.id(this.element[target]) || new Element(lower).inject(this.element, 'top')).empty(); + var data = this.push(items, {}, this[lower], what == 'headers' ? 'th' : 'td'); + + if (what == 'headers') this.head = this.getHead(); + else this.foot = this.getHead(); + + return data; + }, + + getHead: function(){ + var rows = this.thead.rows; + return rows.length > 1 ? $$(rows) : rows.length ? document.id(rows[0]) : false; + }, + + setHeaders: function(headers){ + this.set('headers', headers); + return this; + }, + + setFooters: function(footers){ + this.set('footers', footers); + return this; + }, + + push: function(row, rowProperties, target, tag, where){ + if (typeOf(row) == 'element' && row.get('tag') == 'tr'){ + row.inject(target || this.body, where); + return { + tr: row, + tds: row.getChildren('td') + }; + } + + var tds = row.map(function(data){ + var td = new Element(tag || 'td', data ? data.properties : {}), + content = (data ? data.content : '') || data, + type = typeOf(content); + + if (['element', 'array', 'collection', 'elements'].contains(type)) td.adopt(content); + else td.set('html', content); + + return td; + }); + + return { + tr: new Element('tr', rowProperties).inject(target || this.body, where).adopt(tds), + tds: tds + }; + } + +}); + + +['adopt', 'inject', 'wraps', 'grab', 'replaces', 'dispose'].each(function(method){ + HtmlTable.implement(method, function(){ + this.element[method].apply(this.element, arguments); + return this; + }); +}); + + + + +/* +--- + +script: HtmlTable.Zebra.js + +name: HtmlTable.Zebra + +description: Builds a stripy table with methods to add rows. + +license: MIT-style license + +authors: + - Harald Kirschner + - Aaron Newton + +requires: + - /HtmlTable + - /Class.refactor + +provides: [HtmlTable.Zebra] + +... +*/ + +HtmlTable = Class.refactor(HtmlTable, { + + options: { + classZebra: 'table-tr-odd', + zebra: true + }, + + initialize: function(){ + this.previous.apply(this, arguments); + if (this.occluded) return this.occluded; + if (this.options.zebra) this.updateZebras(); + }, + + updateZebras: function(){ + Array.each(this.body.rows, this.zebra, this); + }, + + setRowStyle: function(row, i){ + if (this.previous) this.previous(row, i); + this.zebra(row, i); + }, + + zebra: function(row, i){ + return row[((i % 2) ? 'remove' : 'add')+'Class'](this.options.classZebra); + }, + + push: function(){ + var pushed = this.previous.apply(this, arguments); + if (this.options.zebra) this.updateZebras(); + return pushed; + } + +}); + + +/* +--- + +script: HtmlTable.Sort.js + +name: HtmlTable.Sort + +description: Builds a stripy, sortable table with methods to add rows. + +license: MIT-style license + +authors: + - Harald Kirschner + - Aaron Newton + - Jacob Thornton + +requires: + - Core/Hash + - /HtmlTable + - /Class.refactor + - /Element.Delegation + - /String.Extras + - /Date + +provides: [HtmlTable.Sort] + +... +*/ + +HtmlTable = Class.refactor(HtmlTable, { + + options: {/* + onSort: function(){}, */ + sortIndex: 0, + sortReverse: false, + parsers: [], + defaultParser: 'string', + classSortable: 'table-sortable', + classHeadSort: 'table-th-sort', + classHeadSortRev: 'table-th-sort-rev', + classNoSort: 'table-th-nosort', + classGroupHead: 'table-tr-group-head', + classGroup: 'table-tr-group', + classCellSort: 'table-td-sort', + classSortSpan: 'table-th-sort-span', + sortable: false, + thSelector: 'th' + }, + + initialize: function (){ + this.previous.apply(this, arguments); + if (this.occluded) return this.occluded; + this.sorted = {index: null, dir: 1}; + this.bound = { + headClick: this.headClick.bind(this) + }; + this.sortSpans = new Elements(); + if (this.options.sortable){ + this.enableSort(); + if (this.options.sortIndex != null) this.sort(this.options.sortIndex, this.options.sortReverse); + } + }, + + attachSorts: function(attach){ + this.detachSorts(); + if (attach !== false) this.element.addEvent('click:relay(' + this.options.thSelector + ')', this.bound.headClick); + }, + + detachSorts: function(){ + this.element.removeEvents('click:relay(' + this.options.thSelector + ')'); + }, + + setHeaders: function(){ + this.previous.apply(this, arguments); + if (this.sortEnabled) this.setParsers(); + }, + + setParsers: function(){ + this.parsers = this.detectParsers(); + }, + + detectParsers: function(){ + return this.head && this.head.getElements(this.options.thSelector).flatten().map(this.detectParser, this); + }, + + detectParser: function(cell, index){ + if (cell.hasClass(this.options.classNoSort) || cell.retrieve('htmltable-parser')) return cell.retrieve('htmltable-parser'); + var thDiv = new Element('div'); + thDiv.adopt(cell.childNodes).inject(cell); + var sortSpan = new Element('span', {'class': this.options.classSortSpan}).inject(thDiv, 'top'); + this.sortSpans.push(sortSpan); + var parser = this.options.parsers[index], + rows = this.body.rows, + cancel; + switch (typeOf(parser)){ + case 'function': parser = {convert: parser}; cancel = true; break; + case 'string': parser = parser; cancel = true; break; + } + if (!cancel){ + HtmlTable.ParserPriority.some(function(parserName){ + var current = HtmlTable.Parsers[parserName], + match = current.match; + if (!match) return false; + for (var i = 0, j = rows.length; i < j; i++){ + var cell = document.id(rows[i].cells[index]), + text = cell ? cell.get('html').clean() : ''; + if (text && match.test(text)){ + parser = current; + return true; + } + } + }); + } + if (!parser) parser = this.options.defaultParser; + cell.store('htmltable-parser', parser); + return parser; + }, + + headClick: function(event, el){ + if (!this.head || el.hasClass(this.options.classNoSort)) return; + return this.sort(Array.indexOf(this.head.getElements(this.options.thSelector).flatten(), el) % this.body.rows[0].cells.length); + }, + + serialize: function() { + var previousSerialization = this.previous.apply(this, arguments) || {}; + if (this.options.sortable) { + previousSerialization.sortIndex = this.sorted.index; + previousSerialization.sortReverse = this.sorted.reverse; + } + return previousSerialization; + }, + + restore: function(tableState) { + if(this.options.sortable && tableState.sortIndex) { + this.sort(tableState.sortIndex, tableState.sortReverse); + } + this.previous.apply(this, arguments); + }, + + setSortedState: function(index, reverse){ + if (reverse != null) this.sorted.reverse = reverse; + else if (this.sorted.index == index) this.sorted.reverse = !this.sorted.reverse; + else this.sorted.reverse = this.sorted.index == null; + + if (index != null) this.sorted.index = index; + }, + + setHeadSort: function(sorted){ + var head = $$(!this.head.length ? this.head.cells[this.sorted.index] : this.head.map(function(row){ + return row.getElements(this.options.thSelector)[this.sorted.index]; + }, this).clean()); + if (!head.length) return; + if (sorted){ + head.addClass(this.options.classHeadSort); + if (this.sorted.reverse) head.addClass(this.options.classHeadSortRev); + else head.removeClass(this.options.classHeadSortRev); + } else { + head.removeClass(this.options.classHeadSort).removeClass(this.options.classHeadSortRev); + } + }, + + setRowSort: function(data, pre){ + var count = data.length, + body = this.body, + group, + rowIndex; + + while (count){ + var item = data[--count], + position = item.position, + row = body.rows[position]; + + if (row.disabled) continue; + if (!pre){ + group = this.setGroupSort(group, row, item); + this.setRowStyle(row, count); + } + body.appendChild(row); + + for (rowIndex = 0; rowIndex < count; rowIndex++){ + if (data[rowIndex].position > position) data[rowIndex].position--; + } + } + }, + + setRowStyle: function(row, i){ + this.previous(row, i); + row.cells[this.sorted.index].addClass(this.options.classCellSort); + }, + + setGroupSort: function(group, row, item){ + if (group == item.value) row.removeClass(this.options.classGroupHead).addClass(this.options.classGroup); + else row.removeClass(this.options.classGroup).addClass(this.options.classGroupHead); + return item.value; + }, + + getParser: function(){ + var parser = this.parsers[this.sorted.index]; + return typeOf(parser) == 'string' ? HtmlTable.Parsers[parser] : parser; + }, + + sort: function(index, reverse, pre){ + if (!this.head) return; + + if (!pre){ + this.clearSort(); + this.setSortedState(index, reverse); + this.setHeadSort(true); + } + + var parser = this.getParser(); + if (!parser) return; + + var rel; + if (!Browser.ie){ + rel = this.body.getParent(); + this.body.dispose(); + } + + var data = this.parseData(parser).sort(function(a, b){ + if (a.value === b.value) return 0; + return a.value > b.value ? 1 : -1; + }); + + if (this.sorted.reverse == (parser == HtmlTable.Parsers['input-checked'])) data.reverse(true); + this.setRowSort(data, pre); + + if (rel) rel.grab(this.body); + this.fireEvent('stateChanged'); + return this.fireEvent('sort', [this.body, this.sorted.index]); + }, + + parseData: function(parser){ + return Array.map(this.body.rows, function(row, i){ + var value = parser.convert.call(document.id(row.cells[this.sorted.index])); + return { + position: i, + value: value + }; + }, this); + }, + + clearSort: function(){ + this.setHeadSort(false); + this.body.getElements('td').removeClass(this.options.classCellSort); + }, + + reSort: function(){ + if (this.sortEnabled) this.sort.call(this, this.sorted.index, this.sorted.reverse); + return this; + }, + + enableSort: function(){ + this.element.addClass(this.options.classSortable); + this.attachSorts(true); + this.setParsers(); + this.sortEnabled = true; + return this; + }, + + disableSort: function(){ + this.element.removeClass(this.options.classSortable); + this.attachSorts(false); + this.sortSpans.each(function(span){ + span.destroy(); + }); + this.sortSpans.empty(); + this.sortEnabled = false; + return this; + } + +}); + +HtmlTable.ParserPriority = ['date', 'input-checked', 'input-value', 'float', 'number']; + +HtmlTable.Parsers = { + + 'date': { + match: /^\d{2}[-\/ ]\d{2}[-\/ ]\d{2,4}$/, + convert: function(){ + var d = Date.parse(this.get('text').stripTags()); + return (typeOf(d) == 'date') ? d.format('db') : ''; + }, + type: 'date' + }, + 'input-checked': { + match: / type="(radio|checkbox)" /, + convert: function(){ + return this.getElement('input').checked; + } + }, + 'input-value': { + match: /= rows.length) index = null; + + return index; + }, + + attachSelects: function(attach){ + attach = attach != null ? attach : true; + + var method = attach ? 'addEvents' : 'removeEvents'; + this.element[method]({ + mouseleave: this.bound.mouseleave, + click: this.bound.activateKeyboard + }); + + this.body[method]({ + 'click:relay(tr)': this.bound.clickRow, + 'contextmenu:relay(tr)': this.bound.clickRow + }); + + if (this.options.useKeyboard || this.keyboard){ + if (!this.keyboard) this.keyboard = new Keyboard(); + if (!this.selectKeysDefined) { + this.selectKeysDefined = true; + var timer, held; + + var move = function(offset){ + var mover = function(e){ + clearTimeout(timer); + e.preventDefault(); + + var to = this.body.rows[this.getRowByOffset(offset)]; + if (e.shift && to && this.isSelected(to)){ + this.deselectRow(this.focused); + this.focused = to; + } else { + if (to && (!this.options.allowMultiSelect || !e.shift)){ + this.selectNone(); + } + this.shiftFocus(offset, e); + } + + if (held){ + timer = mover.delay(100, this, e); + } else { + timer = (function(){ + held = true; + mover(e); + }).delay(400); + } + }.bind(this); + return mover; + }.bind(this); + + var clear = function(){ + clearTimeout(timer); + held = false; + }; + + this.keyboard.addEvents({ + 'keydown:shift+up': move(-1), + 'keydown:shift+down': move(1), + 'keyup:shift+up': clear, + 'keyup:shift+down': clear, + 'keyup:up': clear, + 'keyup:down': clear + }); + + var shiftHint = ''; + if (this.options.allowMultiSelect && this.options.shiftForMultiSelect && this.options.useKeyboard){ + shiftHint = " (Shift multi-selects)."; + } + + this.keyboard.addShortcuts({ + 'Select Previous Row': { + keys: 'up', + shortcut: 'up arrow', + handler: move(-1), + description: 'Select the previous row in the table.' + shiftHint + }, + 'Select Next Row': { + keys: 'down', + shortcut: 'down arrow', + handler: move(1), + description: 'Select the next row in the table.' + shiftHint + } + }); + + } + this.keyboard[attach ? 'activate' : 'deactivate'](); + } + this.updateSelects(); + }, + + mouseleave: function(){ + if (this.hovered) this.leaveRow(this.hovered); + } + +}); + + +/* +--- + +script: Scroller.js + +name: Scroller + +description: Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries. + +license: MIT-style license + +authors: + - Valerio Proietti + +requires: + - Core/Events + - Core/Options + - Core/Element.Event + - Core/Element.Dimensions + - MooTools.More + +provides: [Scroller] + +... +*/ + +var Scroller = new Class({ + + Implements: [Events, Options], + + options: { + area: 20, + velocity: 1, + onChange: function(x, y){ + this.element.scrollTo(x, y); + }, + fps: 50 + }, + + initialize: function(element, options){ + this.setOptions(options); + this.element = document.id(element); + this.docBody = document.id(this.element.getDocument().body); + this.listener = (typeOf(this.element) != 'element') ? this.docBody : this.element; + this.timer = null; + this.bound = { + attach: this.attach.bind(this), + detach: this.detach.bind(this), + getCoords: this.getCoords.bind(this) + }; + }, + + start: function(){ + this.listener.addEvents({ + mouseover: this.bound.attach, + mouseleave: this.bound.detach + }); + return this; + }, + + stop: function(){ + this.listener.removeEvents({ + mouseover: this.bound.attach, + mouseleave: this.bound.detach + }); + this.detach(); + this.timer = clearInterval(this.timer); + return this; + }, + + attach: function(){ + this.listener.addEvent('mousemove', this.bound.getCoords); + }, + + detach: function(){ + this.listener.removeEvent('mousemove', this.bound.getCoords); + this.timer = clearInterval(this.timer); + }, + + getCoords: function(event){ + this.page = (this.listener.get('tag') == 'body') ? event.client : event.page; + if (!this.timer) this.timer = this.scroll.periodical(Math.round(1000 / this.options.fps), this); + }, + + scroll: function(){ + var size = this.element.getSize(), + scroll = this.element.getScroll(), + pos = this.element != this.docBody ? this.element.getOffsets() : {x: 0, y:0}, + scrollSize = this.element.getScrollSize(), + change = {x: 0, y: 0}, + top = this.options.area.top || this.options.area, + bottom = this.options.area.bottom || this.options.area; + for (var z in this.page){ + if (this.page[z] < (top + pos[z]) && scroll[z] != 0){ + change[z] = (this.page[z] - top - pos[z]) * this.options.velocity; + } else if (this.page[z] + bottom > (size[z] + pos[z]) && scroll[z] + size[z] != scrollSize[z]){ + change[z] = (this.page[z] - size[z] + bottom - pos[z]) * this.options.velocity; + } + change[z] = change[z].round(); + } + if (change.y || change.x) this.fireEvent('change', [scroll.x + change.x, scroll.y + change.y]); + } + +}); + + +/* +--- + +script: Tips.js + +name: Tips + +description: Class for creating nice tips that follow the mouse cursor when hovering an element. + +license: MIT-style license + +authors: + - Valerio Proietti + - Christoph Pojer + - Luis Merino + +requires: + - Core/Options + - Core/Events + - Core/Element.Event + - Core/Element.Style + - Core/Element.Dimensions + - /MooTools.More + +provides: [Tips] + +... +*/ + +(function(){ + +var read = function(option, element){ + return (option) ? (typeOf(option) == 'function' ? option(element) : element.get(option)) : ''; +}; + +this.Tips = new Class({ + + Implements: [Events, Options], + + options: {/* + onAttach: function(element){}, + onDetach: function(element){}, + onBound: function(coords){},*/ + onShow: function(){ + this.tip.setStyle('display', 'block'); + }, + onHide: function(){ + this.tip.setStyle('display', 'none'); + }, + title: 'title', + text: function(element){ + return element.get('rel') || element.get('href'); + }, + showDelay: 100, + hideDelay: 100, + className: 'tip-wrap', + offset: {x: 16, y: 16}, + windowPadding: {x:0, y:0}, + fixed: false + }, + + initialize: function(){ + var params = Array.link(arguments, { + options: Type.isObject, + elements: function(obj){ + return obj != null; + } + }); + this.setOptions(params.options); + if (params.elements) this.attach(params.elements); + this.container = new Element('div', {'class': 'tip'}); + }, + + toElement: function(){ + if (this.tip) return this.tip; + + this.tip = new Element('div', { + 'class': this.options.className, + styles: { + position: 'absolute', + top: 0, + left: 0 + } + }).adopt( + new Element('div', {'class': 'tip-top'}), + this.container, + new Element('div', {'class': 'tip-bottom'}) + ); + + return this.tip; + }, + + attach: function(elements){ + $$(elements).each(function(element){ + var title = read(this.options.title, element), + text = read(this.options.text, element); + + element.set('title', '').store('tip:native', title).retrieve('tip:title', title); + element.retrieve('tip:text', text); + this.fireEvent('attach', [element]); + + var events = ['enter', 'leave']; + if (!this.options.fixed) events.push('move'); + + events.each(function(value){ + var event = element.retrieve('tip:' + value); + if (!event) event = function(event){ + this['element' + value.capitalize()].apply(this, [event, element]); + }.bind(this); + + element.store('tip:' + value, event).addEvent('mouse' + value, event); + }, this); + }, this); + + return this; + }, + + detach: function(elements){ + $$(elements).each(function(element){ + ['enter', 'leave', 'move'].each(function(value){ + element.removeEvent('mouse' + value, element.retrieve('tip:' + value)).eliminate('tip:' + value); + }); + + this.fireEvent('detach', [element]); + + if (this.options.title == 'title'){ // This is necessary to check if we can revert the title + var original = element.retrieve('tip:native'); + if (original) element.set('title', original); + } + }, this); + + return this; + }, + + elementEnter: function(event, element){ + clearTimeout(this.timer); + this.timer = (function(){ + this.container.empty(); + + ['title', 'text'].each(function(value){ + var content = element.retrieve('tip:' + value); + var div = this['_' + value + 'Element'] = new Element('div', { + 'class': 'tip-' + value + }).inject(this.container); + if (content) this.fill(div, content); + }, this); + this.show(element); + this.position((this.options.fixed) ? {page: element.getPosition()} : event); + }).delay(this.options.showDelay, this); + }, + + elementLeave: function(event, element){ + clearTimeout(this.timer); + this.timer = this.hide.delay(this.options.hideDelay, this, element); + this.fireForParent(event, element); + }, + + setTitle: function(title){ + if (this._titleElement){ + this._titleElement.empty(); + this.fill(this._titleElement, title); + } + return this; + }, + + setText: function(text){ + if (this._textElement){ + this._textElement.empty(); + this.fill(this._textElement, text); + } + return this; + }, + + fireForParent: function(event, element){ + element = element.getParent(); + if (!element || element == document.body) return; + if (element.retrieve('tip:enter')) element.fireEvent('mouseenter', event); + else this.fireForParent(event, element); + }, + + elementMove: function(event, element){ + this.position(event); + }, + + position: function(event){ + if (!this.tip) document.id(this); + + var size = window.getSize(), scroll = window.getScroll(), + tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight}, + props = {x: 'left', y: 'top'}, + bounds = {y: false, x2: false, y2: false, x: false}, + obj = {}; + + for (var z in props){ + obj[props[z]] = event.page[z] + this.options.offset[z]; + if (obj[props[z]] < 0) bounds[z] = true; + if ((obj[props[z]] + tip[z] - scroll[z]) > size[z] - this.options.windowPadding[z]){ + obj[props[z]] = event.page[z] - this.options.offset[z] - tip[z]; + bounds[z+'2'] = true; + } + } + + this.fireEvent('bound', bounds); + this.tip.setStyles(obj); + }, + + fill: function(element, contents){ + if (typeof contents == 'string') element.set('html', contents); + else element.adopt(contents); + }, + + show: function(element){ + if (!this.tip) document.id(this); + if (!this.tip.getParent()) this.tip.inject(document.body); + this.fireEvent('show', [this.tip, element]); + }, + + hide: function(element){ + if (!this.tip) document.id(this); + this.fireEvent('hide', [this.tip, element]); + } + +}); + +})(); + + +/* +--- + +name: Locale.en-GB.Date + +description: Date messages for British English. + +license: MIT-style license + +authors: + - Aaron Newton + +requires: + - /Locale + - /Locale.en-US.Date + +provides: [Locale.en-GB.Date] + +... +*/ + +Locale.define('en-GB', 'Date', { + + // Culture's date order: DD/MM/YYYY + dateOrder: ['date', 'month', 'year'], + shortDate: '%d/%m/%Y', + shortTime: '%H:%M' + +}).inherit('en-US', 'Date'); + diff --git a/web/tools/mootools/mootools-more-1.3.2.1-yc.js b/web/tools/mootools/mootools-more-1.3.2.1-yc.js new file mode 100644 index 000000000..807e27ecf --- /dev/null +++ b/web/tools/mootools/mootools-more-1.3.2.1-yc.js @@ -0,0 +1,742 @@ +// MooTools: the javascript framework. +// Load this file's selection again by visiting: http://mootools.net/more/09f3e47813269cd5026cbf8c1f828e72 +// Or build this file again with packager using: packager build More/Chain.Wait More/Array.Extras More/Date More/Date.Extras More/Number.Format More/String.Extras More/String.QueryString More/URI More/URI.Relative More/Hash More/Hash.Extras More/Element.Forms More/Elements.From More/Element.Event.Pseudos.Keys More/Element.Pin More/Element.Position More/Element.Shortcuts More/Form.Request More/Form.Request.Append More/Form.Validator.Inline More/Form.Validator.Extras More/OverText More/Fx.Accordion More/Fx.Move More/Fx.Reveal More/Fx.Slide More/Fx.SmoothScroll More/Fx.Sort More/Drag.Move More/Slider More/Sortables More/Request.JSONP More/Request.Queue More/Request.Periodical More/Assets More/Color More/Group More/Hash.Cookie More/Table More/HtmlTable.Zebra More/HtmlTable.Sort More/HtmlTable.Select More/Keyboard.Extras More/Mask More/Scroller More/Tips More/Locale.en-GB.Date +/* +--- +copyrights: + - [MooTools](http://mootools.net) + +licenses: + - [MIT License](http://mootools.net/license.txt) +... +*/ +MooTools.More={version:"1.3.2.1",build:"e586bcd2496e9b22acfde32e12f84d49ce09e59d"};(function(){var a={wait:function(b){return this.chain(function(){this.callChain.delay(b==null?500:b,this); +return this;}.bind(this));}};Chain.implement(a);if(this.Fx){Fx.implement(a);}if(this.Element&&Element.implement&&this.Fx){Element.implement({chains:function(b){Array.from(b||["tween","morph","reveal"]).each(function(c){c=this.get(c); +if(!c){return;}c.setOptions({link:"chain"});},this);return this;},pauseFx:function(c,b){this.chains(b).get(b||"tween").wait(c);return this;}});}})();(function(a){Array.implement({min:function(){return Math.min.apply(null,this); +},max:function(){return Math.max.apply(null,this);},average:function(){return this.length?this.sum()/this.length:0;},sum:function(){var b=0,c=this.length; +if(c){while(c--){b+=this[c];}}return b;},unique:function(){return[].combine(this);},shuffle:function(){for(var c=this.length;c&&--c;){var b=this[c],d=Math.floor(Math.random()*(c+1)); +this[c]=this[d];this[d]=b;}return this;},reduce:function(d,e){for(var c=0,b=this.length;c3&&a<21)?"th":["th","st","nd","rd","th"][Math.min(a%10,4)]; +},lessThanMinuteAgo:"less than a minute ago",minuteAgo:"about a minute ago",minutesAgo:"{delta} minutes ago",hourAgo:"about an hour ago",hoursAgo:"about {delta} hours ago",dayAgo:"1 day ago",daysAgo:"{delta} days ago",weekAgo:"1 week ago",weeksAgo:"{delta} weeks ago",monthAgo:"1 month ago",monthsAgo:"{delta} months ago",yearAgo:"1 year ago",yearsAgo:"{delta} years ago",lessThanMinuteUntil:"less than a minute from now",minuteUntil:"about a minute from now",minutesUntil:"{delta} minutes from now",hourUntil:"about an hour from now",hoursUntil:"about {delta} hours from now",dayUntil:"1 day from now",daysUntil:"{delta} days from now",weekUntil:"1 week from now",weeksUntil:"{delta} weeks from now",monthUntil:"1 month from now",monthsUntil:"{delta} months from now",yearUntil:"1 year from now",yearsUntil:"{delta} years from now"}); +(function(){var a=this.Date;var f=a.Methods={ms:"Milliseconds",year:"FullYear",min:"Minutes",mo:"Month",sec:"Seconds",hr:"Hours"};["Date","Day","FullYear","Hours","Milliseconds","Minutes","Month","Seconds","Time","TimezoneOffset","Week","Timezone","GMTOffset","DayOfYear","LastMonth","LastDayOfMonth","UTCDate","UTCDay","UTCFullYear","AMPM","Ordinal","UTCHours","UTCMilliseconds","UTCMinutes","UTCMonth","UTCSeconds","UTCMilliseconds"].each(function(t){a.Methods[t.toLowerCase()]=t; +});var p=function(v,u,t){if(u==1){return v;}return v28){return 1;}if(z==0&&t<-2){y=new a(y).decrement("day",v); +v=0;}x=new a(y.get("year"),0,1).get("day")||7;if(x>4){u=-7;}}else{x=new a(y.get("year"),0,1).get("day");}u+=y.get("dayofyear");u+=6-v;u+=(7+x-w)%7;return(u/7); +},getOrdinal:function(t){return a.getMsg("ordinal",t||this.get("date"));},getTimezone:function(){return this.toString().replace(/^.*? ([A-Z]{3}).[0-9]{4}.*$/,"$1").replace(/^.*?\(([A-Z])[a-z]+ ([A-Z])[a-z]+ ([A-Z])[a-z]+\)$/,"$1$2$3"); +},getGMTOffset:function(){var t=this.get("timezoneOffset");return((t>0)?"-":"+")+p((t.abs()/60).floor(),2)+p(t%60,2);},setAMPM:function(t){t=t.toUpperCase(); +var u=this.get("hr");if(u>11&&t=="AM"){return this.decrement("hour",12);}else{if(u<12&&t=="PM"){return this.increment("hour",12);}}return this;},getAMPM:function(){return(this.get("hr")<12)?"AM":"PM"; +},parse:function(t){this.set("time",a.parse(t));return this;},isValid:function(t){return !isNaN((t||this).valueOf());},format:function(u){if(!this.isValid()){return"invalid date"; +}if(!u){u="%x %X";}var t=u.toLowerCase();if(s[t]){return s[t](this);}u=g[t]||u;var v=this;return u.replace(/%([a-z%])/gi,function(x,w){switch(w){case"a":return a.getMsg("days_abbr")[v.get("day")]; +case"A":return a.getMsg("days")[v.get("day")];case"b":return a.getMsg("months_abbr")[v.get("month")];case"B":return a.getMsg("months")[v.get("month")]; +case"c":return v.format("%a %b %d %H:%M:%S %Y");case"d":return p(v.get("date"),2);case"e":return p(v.get("date"),2," ");case"H":return p(v.get("hr"),2); +case"I":return p((v.get("hr")%12)||12,2);case"j":return p(v.get("dayofyear"),3);case"k":return p(v.get("hr"),2," ");case"l":return p((v.get("hr")%12)||12,2," "); +case"L":return p(v.get("ms"),3);case"m":return p((v.get("mo")+1),2);case"M":return p(v.get("min"),2);case"o":return v.get("ordinal");case"p":return a.getMsg(v.get("ampm")); +case"s":return Math.round(v/1000);case"S":return p(v.get("seconds"),2);case"T":return v.format("%H:%M:%S");case"U":return p(v.get("week"),2);case"w":return v.get("day"); +case"x":return v.format(a.getMsg("shortDate"));case"X":return v.format(a.getMsg("shortTime"));case"y":return v.get("year").toString().substr(2);case"Y":return v.get("year"); +case"z":return v.get("GMTOffset");case"Z":return v.get("Timezone");}return w;});},toISOString:function(){return this.format("iso8601");}}).alias({toJSON:"toISOString",compare:"diff",strftime:"format"}); +var g={db:"%Y-%m-%d %H:%M:%S",compact:"%Y%m%dT%H%M%S","short":"%d %b %H:%M","long":"%B %d, %Y %H:%M"};var k=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],h=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; +var s={rfc822:function(t){return k[t.get("day")]+t.format(", %d ")+h[t.get("month")]+t.format(" %Y %H:%M:%S %Z");},rfc2822:function(t){return k[t.get("day")]+t.format(", %d ")+h[t.get("month")]+t.format(" %Y %H:%M:%S %z"); +},iso8601:function(t){return(t.getUTCFullYear()+"-"+p(t.getUTCMonth()+1,2)+"-"+p(t.getUTCDate(),2)+"T"+p(t.getUTCHours(),2)+":"+p(t.getUTCMinutes(),2)+":"+p(t.getUTCSeconds(),2)+"."+p(t.getUTCMilliseconds(),3)+"Z"); +}};var c=[],n=a.parse;var r=function(w,y,v){var u=-1,x=a.getMsg(w+"s");switch(typeOf(y)){case"object":u=x[y.get(w)];break;case"number":u=x[y];if(!u){throw new Error("Invalid "+w+" index: "+y); +}break;case"string":var t=x.filter(function(z){return this.test(z);},new RegExp("^"+y,"i"));if(!t.length){throw new Error("Invalid "+w+" string");}if(t.length>1){throw new Error("Ambiguous "+w); +}u=t[0];}return(v)?x.indexOf(u):u;};var i=1900,o=70;a.extend({getMsg:function(u,t){return Locale.get("Date."+u,t);},units:{ms:Function.from(1),second:Function.from(1000),minute:Function.from(60000),hour:Function.from(3600000),day:Function.from(86400000),week:Function.from(608400000),month:function(u,t){var v=new a; +return a.daysInMonth(u!=null?u:v.get("mo"),t!=null?t:v.get("year"))*86400000;},year:function(t){t=t||new a().get("year");return a.isLeapYear(t)?31622400000:31536000000; +}},daysInMonth:function(u,t){return[31,a.isLeapYear(t)?29:28,31,30,31,30,31,31,30,31,30,31][u];},isLeapYear:function(t){return((t%4===0)&&(t%100!==0))||(t%400===0); +},parse:function(w){var v=typeOf(w);if(v=="number"){return new a(w);}if(v!="string"){return w;}w=w.clean();if(!w.length){return null;}var u;c.some(function(x){var t=x.re.exec(w); +return(t)?(u=x.handler(t)):false;});if(!(u&&u.isValid())){u=new a(n(w));if(!(u&&u.isValid())){u=new a(w.toInt());}}return u;},parseDay:function(t,u){return r("day",t,u); +},parseMonth:function(u,t){return r("month",u,t);},parseUTC:function(u){var t=new a(u);var v=a.UTC(t.get("year"),t.get("mo"),t.get("date"),t.get("hr"),t.get("min"),t.get("sec"),t.get("ms")); +return new a(v);},orderIndex:function(t){return a.getMsg("dateOrder").indexOf(t)+1;},defineFormat:function(t,u){g[t]=u;return this;},defineFormats:function(t){for(var u in t){a.defineFormat(u,t[u]); +}return this;},defineParser:function(t){c.push((t.re&&t.handler)?t:l(t));return this;},defineParsers:function(){Array.flatten(arguments).each(a.defineParser); +return this;},define2DigitYearStart:function(t){o=t%100;i=t-o;return this;}});var d=function(t){return new RegExp("(?:"+a.getMsg(t).map(function(u){return u.substr(0,3); +}).join("|")+")[a-z]*");};var m=function(t){switch(t){case"T":return"%H:%M:%S";case"x":return((a.orderIndex("month")==1)?"%m[-./]%d":"%d[-./]%m")+"([-./]%y)?"; +case"X":return"%H([.:]%M)?([.:]%S([.:]%s)?)? ?%p? ?%z?";}return null;};var j={d:/[0-2]?[0-9]|3[01]/,H:/[01]?[0-9]|2[0-3]/,I:/0?[1-9]|1[0-2]/,M:/[0-5]?\d/,s:/\d+/,o:/[a-z]*/,p:/[ap]\.?m\.?/,y:/\d{2}|\d{4}/,Y:/\d{4}/,z:/Z|[+-]\d{2}(?::?\d{2})?/}; +j.m=j.I;j.S=j.M;var e;var b=function(t){e=t;j.a=j.A=d("days");j.b=j.B=d("months");c.each(function(v,u){if(v.format){c[u]=l(v.format);}});};var l=function(v){if(!e){return{format:v}; +}var t=[];var u=(v.source||v).replace(/%([a-z])/gi,function(x,w){return m(w)||x;}).replace(/\((?!\?)/g,"(?:").replace(/ (?!\?|\*)/g,",? ").replace(/%([a-z%])/gi,function(x,w){var y=j[w]; +if(!y){return w;}t.push(w);return"("+y.source+")";}).replace(/\[a-z\]/gi,"[a-z\\u00c0-\\uffff;&]");return{format:v,re:new RegExp("^"+u+"$","i"),handler:function(z){z=z.slice(1).associate(t); +var w=new a().clearTime(),y=z.y||z.Y;if(y!=null){q.call(w,"y",y);}if("d" in z){q.call(w,"d",1);}if("m" in z||z.b||z.B){q.call(w,"m",1);}for(var x in z){q.call(w,x,z[x]); +}return w;}};};var q=function(t,u){if(!u){return this;}switch(t){case"a":case"A":return this.set("day",a.parseDay(u,true));case"b":case"B":return this.set("mo",a.parseMonth(u,true)); +case"d":return this.set("date",u);case"H":case"I":return this.set("hr",u);case"m":return this.set("mo",u-1);case"M":return this.set("min",u);case"p":return this.set("ampm",u.replace(/\./g,"")); +case"S":return this.set("sec",u);case"s":return this.set("ms",("0."+u)*1000);case"w":return this.set("day",u);case"Y":return this.set("year",u);case"y":u=+u; +if(u<100){u+=i+(u0.75*a){e=c;}break;}f/=a;e=c+"s";}f=f.round();return Date.getMsg(e+d,f).substitute({delta:f});}}).defineParsers({re:/^(?:tod|tom|yes)/i,handler:function(a){var b=new Date().clearTime(); +switch(a[0]){case"tom":return b.increment();case"yes":return b.decrement();default:return b;}}},{re:/^(next|last) ([a-z]+)$/i,handler:function(e){var f=new Date().clearTime(); +var b=f.getDay();var c=Date.parseDay(e[2],true);var a=c-b;if(c<=b){a+=7;}if(e[1]=="last"){a-=7;}return f.set("date",f.getDate()+a);}}).alias("timeAgoInWords","timeDiffInWords"); +Locale.define("en-US","Number",{decimal:".",group:",",currency:{prefix:"$ "}});Number.implement({format:function(q){var n=this;q=q?Object.clone(q):{};var a=function(i){if(q[i]!=null){return q[i]; +}return Locale.get("Number."+i);};var f=n<0,h=a("decimal"),k=a("precision"),o=a("group"),c=a("decimals");if(f){var e=a("negative")||{};if(e.prefix==null&&e.suffix==null){e.prefix="-"; +}["prefix","suffix"].each(function(i){if(e[i]){q[i]=a(i)+e[i];}});n=-n;}var l=a("prefix"),p=a("suffix");if(c!==""&&c>=0&&c<=20){n=n.toFixed(c);}if(k>=1&&k<=21){n=(+n).toPrecision(k); +}n+="";var m;if(a("scientific")===false&&n.indexOf("e")>-1){var j=n.split("e"),b=+j[1];n=j[0].replace(".","");if(b<0){b=-b-1;m=j[0].indexOf(".");if(m>-1){b-=m-1; +}while(b--){n="0"+n;}n="0."+n;}else{m=j[0].lastIndexOf(".");if(m>-1){b-=j[0].length-m-1;}while(b--){n+="0";}}}if(h!="."){n=n.replace(".",h);}if(o){m=n.lastIndexOf(h); +m=(m>-1)?m:n.length;var d=n.substring(m),g=m;while(g--){if((m-g-1)%3==0&&g!=(m-1)){d=o+d;}d=n.charAt(g)+d;}n=d;}if(l){n=l+n;}if(p){n+=p;}return n;},formatCurrency:function(){var a=Locale.get("Number.currency")||{}; +if(a.scientific==null){a.scientific=false;}if(a.decimals==null){a.decimals=2;}return this.format(a);},formatPercentage:function(){var a=Locale.get("Number.percentage")||{}; +if(a.suffix==null){a.suffix="%";}if(a.decimals==null){a.decimals=2;}return this.format(a);}});(function(){var c={a:/[àáâãäåăą]/g,A:/[ÀÃÂÃÄÅĂĄ]/g,c:/[ćÄç]/g,C:/[ĆČÇ]/g,d:/[ÄÄ‘]/g,D:/[ÄŽÃ]/g,e:/[èéêëěę]/g,E:/[ÈÉÊËĚĘ]/g,g:/[ÄŸ]/g,G:/[Äž]/g,i:/[ìíîï]/g,I:/[ÃŒÃÃŽÃ]/g,l:/[ĺľł]/g,L:/[ĹĽÅ]/g,n:/[ñňń]/g,N:/[ÑŇŃ]/g,o:/[òóôõöøő]/g,O:/[ÒÓÔÕÖØ]/g,r:/[řŕ]/g,R:/[ŘŔ]/g,s:/[Å¡Å¡ÅŸ]/g,S:/[ŠŞŚ]/g,t:/[ťţ]/g,T:/[ŤŢ]/g,ue:/[ü]/g,UE:/[Ãœ]/g,u:/[ùúûůµ]/g,U:/[ÙÚÛŮ]/g,y:/[ÿý]/g,Y:/[ŸÃ]/g,z:/[žźż]/g,Z:/[ŽŹŻ]/g,th:/[þ]/g,TH:/[Þ]/g,dh:/[ð]/g,DH:/[Ã]/g,ss:/[ß]/g,oe:/[Å“]/g,OE:/[Å’]/g,ae:/[æ]/g,AE:/[Æ]/g},b={" ":/[\xa0\u2002\u2003\u2009]/g,"*":/[\xb7]/g,"'":/[\u2018\u2019]/g,'"':/[\u201c\u201d]/g,"...":/[\u2026]/g,"-":/[\u2013]/g,"»":/[\uFFFD]/g}; +var a=function(f,h){var e=f,g;for(g in h){e=e.replace(h[g],g);}return e;};var d=function(e,g){e=e||"";var h=g?"<"+e+"(?!\\w)[^>]*>([\\s\\S]*?)":"]+)?>",f=new RegExp(h,"gi"); +return f;};String.implement({standardize:function(){return a(this,c);},repeat:function(e){return new Array(e+1).join(this);},pad:function(e,h,g){if(this.length>=e){return this; +}var f=(h==null?" ":""+h).repeat(e-this.length).substr(0,e-this.length);if(!g||g=="right"){return this+f;}if(g=="left"){return f+this;}return f.substr(0,(f.length/2).floor())+this+f.substr(0,(f.length/2).ceil()); +},getTags:function(e,f){return this.match(d(e,f))||[];},stripTags:function(e,f){return this.replace(d(e,f),"");},tidy:function(){return a(this,b);},truncate:function(e,f,i){var h=this; +if(f==null&&arguments.length==1){f="…";}if(h.length>e){h=h.substring(0,e);if(i){var g=h.lastIndexOf(i);if(g!=-1){h=h.substr(0,g);}}if(f){h+=f;}}return h; +}});})();String.implement({parseQueryString:function(d,a){if(d==null){d=true;}if(a==null){a=true;}var c=this.split(/[&;]/),b={};if(!c.length){return b; +}c.each(function(i){var e=i.indexOf("=")+1,g=e?i.substr(e):"",f=e?i.substr(0,e-1).match(/([^\]\[]+|(\B)(?=\]))/g):[i],h=b;if(!f){return;}if(a){g=decodeURIComponent(g); +}f.each(function(k,j){if(d){k=decodeURIComponent(k);}var l=h[k];if(j0){c.pop(); +}else{if(f!="."){c.push(f);}}});return c.join("/")+"/";},combine:function(c){return c.value||c.scheme+"://"+(c.user?c.user+(c.password?":"+c.password:"")+"@":"")+(c.host||"")+(c.port&&c.port!=this.schemes[c.scheme]?":"+c.port:"")+(c.directory||"/")+(c.file||"")+(c.query?"?"+c.query:"")+(c.fragment?"#"+c.fragment:""); +},set:function(d,f,e){if(d=="value"){var c=f.match(a.regs.scheme);if(c){c=c[1];}if(c&&this.schemes[c.toLowerCase()]==null){this.parsed={scheme:c,value:f}; +}else{this.parsed=this.parse(f,(e||this).parsed)||(c?{scheme:c,value:f}:{value:f});}}else{if(d=="data"){this.setData(f);}else{this.parsed[d]=f;}}return this; +},get:function(c,d){switch(c){case"value":return this.combine(this.parsed,d?d.parsed:false);case"data":return this.getData();}return this.parsed[c]||""; +},go:function(){document.location.href=this.toString();},toURI:function(){return this;},getData:function(e,d){var c=this.get(d||"query");if(!(c||c===0)){return e?null:{}; +}var f=c.parseQueryString();return e?f[e]:f;},setData:function(c,f,d){if(typeof c=="string"){var e=this.getData();e[arguments[0]]=arguments[1];c=e;}else{if(f){c=Object.merge(this.getData(),c); +}}return this.set(d||"query",Object.toQueryString(c));},clearData:function(c){return this.set(c||"query","");},toString:b,valueOf:b});a.regs={endSlash:/\/$/,scheme:/^(\w+):/,directoryDot:/\.\/|\.$/}; +a.base=new a(Array.from(document.getElements("base[href]",true)).getLast(),{base:document.location});String.implement({toURI:function(c){return new a(this,c); +}});})();Class.refactor=function(b,a){Object.each(a,function(e,d){var c=b.prototype[d];c=(c&&c.$origin)||c||function(){};b.implement(d,(typeof e=="function")?function(){var f=this.previous; +this.previous=c;var g=e.apply(this,arguments);this.previous=f;return g;}:e);});return b;};URI=Class.refactor(URI,{combine:function(f,e){if(!e||f.scheme!=e.scheme||f.host!=e.host||f.port!=e.port){return this.previous.apply(this,arguments); +}var a=f.file+(f.query?"?"+f.query:"")+(f.fragment?"#"+f.fragment:"");if(!e.directory){return(f.directory||(f.file?"":"./"))+a;}var d=e.directory.split("/"),c=f.directory.split("/"),g="",h; +var b=0;for(h=0;h=0||g.parentPositioned||d.allowNegative)?c.x:0).toInt(); +c.top=((c.y>=0||g.parentPositioned||d.allowNegative)?c.y:0).toInt();a.toMinMax(c,d);if(d.relFixedPosition||f.getStyle("position")=="fixed"){a.toRelFixedPosition(f,c); +}if(d.ignoreScroll){a.toIgnoreScroll(f,c);}if(d.ignoreMargins){a.toIgnoreMargins(c,d);}c.left=Math.ceil(c.left);c.top=Math.ceil(c.top);delete c.x;delete c.y; +return c;},setPositionCoordinates:function(k,g,d){var f=k.offset.y,h=k.offset.x,e=(d==document.body)?window.getScroll():d.getPosition(),j=e.y,c=e.x,i=window.getSize(); +switch(k.position.x){case"left":g.x=c+h;break;case"right":g.x=c+h+d.offsetWidth;break;default:g.x=c+((d==document.body?i.x:d.offsetWidth)/2)+h;break;}switch(k.position.y){case"top":g.y=j+f; +break;case"bottom":g.y=j+f+d.offsetHeight;break;default:g.y=j+((d==document.body?i.y:d.offsetHeight)/2)+f;break;}},toMinMax:function(c,d){var f={left:"x",top:"y"},e; +["minimum","maximum"].each(function(g){["left","top"].each(function(h){e=d[g]?d[g][f[h]]:null;if(e!=null&&((g=="minimum")?c[h]e)){c[h]=e;}});}); +},toRelFixedPosition:function(e,c){var d=window.getScroll();c.top+=d.y;c.left+=d.x;},toIgnoreScroll:function(e,d){var c=e.getScroll();d.top-=c.y;d.left-=c.x; +},toIgnoreMargins:function(c,d){c.left+=d.edge.x=="right"?d.dimensions["margin-right"]:(d.edge.x!="center"?-d.dimensions["margin-left"]:-d.dimensions["margin-left"]+((d.dimensions["margin-right"]+d.dimensions["margin-left"])/2)); +c.top+=d.edge.y=="bottom"?d.dimensions["margin-bottom"]:(d.edge.y!="center"?-d.dimensions["margin-top"]:-d.dimensions["margin-top"]+((d.dimensions["margin-bottom"]+d.dimensions["margin-top"])/2)); +},toEdge:function(c,d){var e={},g=d.dimensions,f=d.edge;switch(f.x){case"left":e.x=0;break;case"right":e.x=-g.x-g.computedRight-g.computedLeft;break;default:e.x=-(Math.round(g.totalWidth/2)); +break;}switch(f.y){case"top":e.y=0;break;case"bottom":e.y=-g.y-g.computedTop-g.computedBottom;break;default:e.y=-(Math.round(g.totalHeight/2));break;}c.x+=e.x; +c.y+=e.y;},getCoordinateFromValue:function(c){if(typeOf(c)!="string"){return c;}c=c.toLowerCase();return{x:c.test("left")?"left":(c.test("right")?"right":"center"),y:c.test(/upper|top/)?"top":(c.test("bottom")?"bottom":"center")}; +}};Element.implement({position:function(d){if(d&&(d.x!=null||d.y!=null)){return(b?b.apply(this,arguments):this);}var c=this.setStyle("position","absolute").calculatePosition(d); +return(d&&d.returnPos)?c:this.setStyles(c);},calculatePosition:function(c){return a.getPosition(this,c);}});})(Element.prototype.position);Element.implement({isDisplayed:function(){return this.getStyle("display")!="none"; +},isVisible:function(){var a=this.offsetWidth,b=this.offsetHeight;return(a==0&&b==0)?false:(a>0&&b>0)?true:this.style.display!="none";},toggle:function(){return this[this.isDisplayed()?"hide":"show"](); +},hide:function(){var b;try{b=this.getStyle("display");}catch(a){}if(b=="none"){return this;}return this.store("element:_originalDisplay",b||"").setStyle("display","none"); +},show:function(a){if(!a&&this.isDisplayed()){return this;}a=a||this.retrieve("element:_originalDisplay")||"block";return this.setStyle("display",(a=="none")?"block":a); +},swapClass:function(a,b){return this.removeClass(a).addClass(b);}});Document.implement({clearSelection:function(){if(window.getSelection){var a=window.getSelection(); +if(a&&a.removeAllRanges){a.removeAllRanges();}}else{if(document.selection&&document.selection.empty){try{document.selection.empty();}catch(b){}}}}});Class.Mutators.Binds=function(a){if(!this.prototype.initialize){this.implement("initialize",function(){}); +}return Array.from(a).concat(this.prototype.Binds||[]);};Class.Mutators.initialize=function(a){return function(){Array.from(this.Binds).each(function(b){var c=this[b]; +if(c){this[b]=c.bind(this);}},this);return a.apply(this,arguments);};};Class.Occlude=new Class({occlude:function(c,b){b=document.id(b||this.element);var a=b.retrieve(c||this.property); +if(a&&!this.occluded){return(this.occluded=a);}this.occluded=false;b.store(c||this.property,this);return this.occluded;}});var IframeShim=new Class({Implements:[Options,Events,Class.Occlude],options:{className:"iframeShim",src:'javascript:false;document.write("");',display:false,zIndex:null,margin:0,offset:{x:0,y:0},browsers:(Browser.ie6||(Browser.firefox&&Browser.version<3&&Browser.Platform.mac))},property:"IframeShim",initialize:function(b,a){this.element=document.id(b); +if(this.occlude()){return this.occluded;}this.setOptions(a);this.makeShim();return this;},makeShim:function(){if(this.options.browsers){var c=this.element.getStyle("zIndex").toInt(); +if(!c){c=1;var b=this.element.getStyle("position");if(b=="static"||!b){this.element.setStyle("position","relative");}this.element.setStyle("zIndex",c); +}c=((this.options.zIndex!=null||this.options.zIndex===0)&&c>this.options.zIndex)?this.options.zIndex:c-1;if(c<0){c=1;}this.shim=new Element("iframe",{src:this.options.src,scrolling:"no",frameborder:0,styles:{zIndex:c,position:"absolute",border:"none",filter:"progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)"},"class":this.options.className}).store("IframeShim",this); +var a=(function(){this.shim.inject(this.element,"after");this[this.options.display?"show":"hide"]();this.fireEvent("inject");}).bind(this);if(!IframeShim.ready){window.addEvent("load",a); +}else{a();}}else{this.position=this.hide=this.show=this.dispose=Function.from(this);}},position:function(){if(!IframeShim.ready||!this.shim){return this; +}var a=this.element.measure(function(){return this.getSize();});if(this.options.margin!=undefined){a.x=a.x-(this.options.margin*2);a.y=a.y-(this.options.margin*2); +this.options.offset.x+=this.options.margin;this.options.offset.y+=this.options.margin;}this.shim.set({width:a.x,height:a.y}).position({relativeTo:this.element,offset:this.options.offset}); +return this;},hide:function(){if(this.shim){this.shim.setStyle("display","none");}return this;},show:function(){if(this.shim){this.shim.setStyle("display","block"); +}return this.position();},dispose:function(){if(this.shim){this.shim.dispose();}return this;},destroy:function(){if(this.shim){this.shim.destroy();}return this; +}});window.addEvent("load",function(){IframeShim.ready=true;});var Mask=new Class({Implements:[Options,Events],Binds:["position"],options:{style:{},"class":"mask",maskMargins:false,useIframeShim:true,iframeShimOptions:{}},initialize:function(b,a){this.target=document.id(b)||document.id(document.body); +this.target.store("mask",this);this.setOptions(a);this.render();this.inject();},render:function(){this.element=new Element("div",{"class":this.options["class"],id:this.options.id||"mask-"+String.uniqueID(),styles:Object.merge({},this.options.style,{display:"none"}),events:{click:function(a){this.fireEvent("click",a); +if(this.options.hideOnClick){this.hide();}}.bind(this)}});this.hidden=true;},toElement:function(){return this.element;},inject:function(b,a){a=a||(this.options.inject?this.options.inject.where:"")||this.target==document.body?"inside":"after"; +b=b||(this.options.inject&&this.options.inject.target)||this.target;this.element.inject(b,a);if(this.options.useIframeShim){this.shim=new IframeShim(this.element,this.options.iframeShimOptions); +this.addEvents({show:this.shim.show.bind(this.shim),hide:this.shim.hide.bind(this.shim),destroy:this.shim.destroy.bind(this.shim)});}},position:function(){this.resize(this.options.width,this.options.height); +this.element.position({relativeTo:this.target,position:"topLeft",ignoreMargins:!this.options.maskMargins,ignoreScroll:this.target==document.body});return this; +},resize:function(a,e){var b={styles:["padding","border"]};if(this.options.maskMargins){b.styles.push("margin");}var d=this.target.getComputedSize(b);if(this.target==document.body){this.element.setStyles({width:0,height:0}); +var c=window.getScrollSize();if(d.totalHeight=0&&a.options[a.selectedIndex].value!=""); +}else{return((a.get("value")==null)||(a.get("value").length==0));}}});Form.Validator.addAllThese([["required",{errorMsg:function(){return Form.Validator.getMsg("required"); +},test:function(a){return !Form.Validator.getValidator("IsEmpty").test(a);}}],["minLength",{errorMsg:function(a,b){if(typeOf(b.minLength)!="null"){return Form.Validator.getMsg("minLength").substitute({minLength:b.minLength,length:a.get("value").length}); +}else{return"";}},test:function(a,b){if(typeOf(b.minLength)!="null"){return(a.get("value").length>=(b.minLength||0));}else{return true;}}}],["maxLength",{errorMsg:function(a,b){if(typeOf(b.maxLength)!="null"){return Form.Validator.getMsg("maxLength").substitute({maxLength:b.maxLength,length:a.get("value").length}); +}else{return"";}},test:function(a,b){return a.get("value").length<=(b.maxLength||10000);}}],["validate-integer",{errorMsg:Form.Validator.getMsg.pass("integer"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^(-?[1-9]\d*|0)$/).test(a.get("value")); +}}],["validate-numeric",{errorMsg:Form.Validator.getMsg.pass("numeric"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(a.get("value")); +}}],["validate-digits",{errorMsg:Form.Validator.getMsg.pass("digits"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^[\d() .:\-\+#]+$/.test(a.get("value"))); +}}],["validate-alpha",{errorMsg:Form.Validator.getMsg.pass("alpha"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^[a-zA-Z]+$/).test(a.get("value")); +}}],["validate-alphanum",{errorMsg:Form.Validator.getMsg.pass("alphanum"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||!(/\W/).test(a.get("value")); +}}],["validate-date",{errorMsg:function(a,b){if(Date.parse){var c=b.dateFormat||"%x";return Form.Validator.getMsg("dateSuchAs").substitute({date:new Date().format(c)}); +}else{return Form.Validator.getMsg("dateInFormatMDY");}},test:function(e,g){if(Form.Validator.getValidator("IsEmpty").test(e)){return true;}var a=Locale.getCurrent().sets.Date,b=new RegExp([a.days,a.days_abbr,a.months,a.months_abbr].flatten().join("|"),"i"),i=e.get("value"),f=i.match(/[a-z]+/gi); +if(f&&!f.every(b.exec,b)){return false;}var c=Date.parse(i),h=g.dateFormat||"%x",d=c.format(h);if(d!="invalid date"){e.set("value",d);}return c.isValid(); +}}],["validate-email",{errorMsg:Form.Validator.getMsg.pass("email"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^(?:[a-z0-9!#$%&'*+\/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+\/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(a.get("value")); +}}],["validate-url",{errorMsg:Form.Validator.getMsg.pass("url"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(a.get("value")); +}}],["validate-currency-dollar",{errorMsg:Form.Validator.getMsg.pass("currencyDollar"),test:function(a){return Form.Validator.getValidator("IsEmpty").test(a)||(/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(a.get("value")); +}}],["validate-one-required",{errorMsg:Form.Validator.getMsg.pass("oneRequired"),test:function(a,b){var c=document.id(b["validate-one-required"])||a.getParent(b["validate-one-required"]); +return c.getElements("input").some(function(d){if(["checkbox","radio"].contains(d.get("type"))){return d.get("checked");}return d.get("value");});}}]]); +Element.Properties.validator={set:function(a){this.get("validator").setOptions(a);},get:function(){var a=this.retrieve("validator");if(!a){a=new Form.Validator(this); +this.store("validator",a);}return a;}};Element.implement({validate:function(a){if(a){this.set("validator",a);}return this.get("validator").validate();}}); +Form.Validator.Inline=new Class({Extends:Form.Validator,options:{showError:function(a){if(a.reveal){a.reveal();}else{a.setStyle("display","block");}},hideError:function(a){if(a.dissolve){a.dissolve(); +}else{a.setStyle("display","none");}},scrollToErrorsOnSubmit:true,scrollToErrorsOnBlur:false,scrollToErrorsOnChange:false,scrollFxOptions:{transition:"quad:out",offset:{y:-20}}},initialize:function(b,a){this.parent(b,a); +this.addEvent("onElementValidate",function(g,f,e,h){var d=this.getValidator(e);if(!g&&d.getError(f)){if(h){f.addClass("warning");}var c=this.makeAdvice(e,f,d.getError(f),h); +this.insertAdvice(c,f);this.showAdvice(e,f);}else{this.hideAdvice(e,f);}});},makeAdvice:function(d,f,c,g){var e=(g)?this.warningPrefix:this.errorPrefix; +e+=(this.options.useTitles)?f.title||c:c;var a=(g)?"warning-advice":"validation-advice";var b=this.getAdvice(d,f);if(b){b=b.set("html",e);}else{b=new Element("div",{html:e,styles:{display:"none"},id:"advice-"+d.split(":")[0]+"-"+this.getFieldId(f)}).addClass(a); +}f.store("$moo:advice-"+d,b);return b;},getFieldId:function(a){return a.id?a.id:a.id="input_"+a.name;},showAdvice:function(b,c){var a=this.getAdvice(b,c); +if(a&&!c.retrieve("$moo:"+this.getPropName(b))&&(a.getStyle("display")=="none"||a.getStyle("visiblity")=="hidden"||a.getStyle("opacity")==0)){c.store("$moo:"+this.getPropName(b),true); +this.options.showError(a);this.fireEvent("showAdvice",[c,a,b]);}},hideAdvice:function(b,c){var a=this.getAdvice(b,c);if(a&&c.retrieve("$moo:"+this.getPropName(b))){c.store("$moo:"+this.getPropName(b),false); +this.options.hideError(a);this.fireEvent("hideAdvice",[c,a,b]);}},getPropName:function(a){return"advice"+a;},resetField:function(a){a=document.id(a);if(!a){return this; +}this.parent(a);a.get("validators").each(function(b){this.hideAdvice(b,a);},this);return this;},getAllAdviceMessages:function(d,c){var b=[];if(d.hasClass("ignoreValidation")&&!c){return b; +}var a=d.get("validators").some(function(g){var e=g.test("^warn-")||d.hasClass("warnOnly");if(e){g=g.replace(/^warn-/,"");}var f=this.getValidator(g);if(!f){return; +}b.push({message:f.getError(d),warnOnly:e,passed:f.test(),validator:f});},this);return b;},getAdvice:function(a,b){return b.retrieve("$moo:advice-"+a); +},insertAdvice:function(a,c){var b=c.get("validatorProps");if(!b.msgPos||!document.id(b.msgPos)){if(c.type&&c.type.toLowerCase()=="radio"){c.getParent().adopt(a); +}else{a.inject(document.id(c),"after");}}else{document.id(b.msgPos).grab(a);}},validateField:function(g,f,b){var a=this.parent(g,f);if(((this.options.scrollToErrorsOnSubmit&&b==null)||b)&&!a){var c=document.id(this).getElement(".validation-failed"); +var d=document.id(this).getParent();while(d!=document.body&&d.getScrollSize().y==d.getSize().y){d=d.getParent();}var e=d.retrieve("$moo:fvScroller");if(!e&&window.Fx&&Fx.Scroll){e=new Fx.Scroll(d,this.options.scrollFxOptions); +d.store("$moo:fvScroller",e);}if(c){if(e){e.toElement(c);}else{d.scrollTo(d.getScroll().x,c.getPosition(d).y-20);}}}return a;},watchFields:function(a){a.each(function(b){if(this.options.evaluateFieldsOnBlur){b.addEvent("blur",this.validationMonitor.pass([b,false,this.options.scrollToErrorsOnBlur],this)); +}if(this.options.evaluateFieldsOnChange){b.addEvent("change",this.validationMonitor.pass([b,true,this.options.scrollToErrorsOnChange],this));}},this);}}); +Form.Validator.addAllThese([["validate-enforce-oncheck",{test:function(a,b){var c=a.getParent("form").retrieve("validator");if(!c){return true;}(b.toEnforce||document.id(b.enforceChildrenOf).getElements("input, select, textarea")).map(function(d){if(a.checked){c.enforceField(d); +}else{c.ignoreField(d);c.resetField(d);}});return true;}}],["validate-ignore-oncheck",{test:function(a,b){var c=a.getParent("form").retrieve("validator"); +if(!c){return true;}(b.toIgnore||document.id(b.ignoreChildrenOf).getElements("input, select, textarea")).each(function(d){if(a.checked){c.ignoreField(d); +c.resetField(d);}else{c.enforceField(d);}});return true;}}],["validate-nospace",{errorMsg:function(){return Form.Validator.getMsg("noSpace");},test:function(a,b){return !a.get("value").test(/\s/); +}}],["validate-toggle-oncheck",{test:function(b,c){var d=b.getParent("form").retrieve("validator");if(!d){return true;}var a=c.toToggle||document.id(c.toToggleChildrenOf).getElements("input, select, textarea"); +if(!b.checked){a.each(function(e){d.ignoreField(e);d.resetField(e);});}else{a.each(function(e){d.enforceField(e);});}return true;}}],["validate-reqchk-bynode",{errorMsg:function(){return Form.Validator.getMsg("reqChkByNode"); +},test:function(a,b){return(document.id(b.nodeId).getElements(b.selector||"input[type=checkbox], input[type=radio]")).some(function(c){return c.checked; +});}}],["validate-required-check",{errorMsg:function(a,b){return b.useTitle?a.get("title"):Form.Validator.getMsg("requiredChk");},test:function(a,b){return !!a.checked; +}}],["validate-reqchk-byname",{errorMsg:function(a,b){return Form.Validator.getMsg("reqChkByName").substitute({label:b.label||a.get("type")});},test:function(b,d){var c=d.groupName||b.get("name"); +var a=$$(document.getElementsByName(c)).some(function(g,f){return g.checked;});var e=b.getParent("form").retrieve("validator");if(a&&e){e.resetField(b); +}return a;}}],["validate-match",{errorMsg:function(a,b){return Form.Validator.getMsg("match").substitute({matchName:b.matchName||document.id(b.matchInput).get("name")}); +},test:function(b,c){var d=b.get("value");var a=document.id(c.matchInput)&&document.id(c.matchInput).get("value");return d&&a?d==a:true;}}],["validate-after-date",{errorMsg:function(a,b){return Form.Validator.getMsg("afterDate").substitute({label:b.afterLabel||(b.afterElement?Form.Validator.getMsg("startDate"):Form.Validator.getMsg("currentDate"))}); +},test:function(b,c){var d=document.id(c.afterElement)?Date.parse(document.id(c.afterElement).get("value")):new Date();var a=Date.parse(b.get("value")); +return a&&d?a>=d:true;}}],["validate-before-date",{errorMsg:function(a,b){return Form.Validator.getMsg("beforeDate").substitute({label:b.beforeLabel||(b.beforeElement?Form.Validator.getMsg("endDate"):Form.Validator.getMsg("currentDate"))}); +},test:function(b,c){var d=Date.parse(b.get("value"));var a=document.id(c.beforeElement)?Date.parse(document.id(c.beforeElement).get("value")):new Date(); +return a&&d?a>=d:true;}}],["validate-custom-required",{errorMsg:function(){return Form.Validator.getMsg("required");},test:function(a,b){return a.get("value")!=b.emptyValue; +}}],["validate-same-month",{errorMsg:function(a,b){var c=document.id(b.sameMonthAs)&&document.id(b.sameMonthAs).get("value");var d=a.get("value");if(d!=""){return Form.Validator.getMsg(c?"sameMonth":"startMonth"); +}},test:function(a,b){var d=Date.parse(a.get("value"));var c=Date.parse(document.id(b.sameMonthAs)&&document.id(b.sameMonthAs).get("value"));return d&&c?d.format("%B")==c.format("%B"):true; +}}],["validate-cc-num",{errorMsg:function(a){var b=a.get("value").replace(/[^0-9]/g,"");return Form.Validator.getMsg("creditcard").substitute({length:b.length}); +},test:function(c){if(Form.Validator.getValidator("IsEmpty").test(c)){return true;}var g=c.get("value");g=g.replace(/[^0-9]/g,"");var a=false;if(g.test(/^4[0-9]{12}([0-9]{3})?$/)){a="Visa"; +}else{if(g.test(/^5[1-5]([0-9]{14})$/)){a="Master Card";}else{if(g.test(/^3[47][0-9]{13}$/)){a="American Express";}else{if(g.test(/^6011[0-9]{12}$/)){a="Discover"; +}}}}if(a){var d=0;var e=0;for(var b=g.length-1;b>=0;--b){e=g.charAt(b).toInt();if(e==0){continue;}if((g.length-b)%2==0){e+=e;}if(e>9){e=e.toString().charAt(0).toInt()+e.toString().charAt(1).toInt(); +}d+=e;}if((d%10)==0){return true;}}var f="";while(g!=""){f+=" "+g.substr(0,4);g=g.substr(4);}c.getParent("form").retrieve("validator").ignoreField(c);c.set("value",f.clean()); +c.getParent("form").retrieve("validator").enforceField(c);return false;}}]]);var OverText=new Class({Implements:[Options,Events,Class.Occlude],Binds:["reposition","assert","focus","hide"],options:{element:"label",labelClass:"overTxtLabel",positionOptions:{position:"upperLeft",edge:"upperLeft",offset:{x:4,y:2}},poll:false,pollInterval:250,wrap:false},property:"OverText",initialize:function(b,a){b=this.element=document.id(b); +if(this.occlude()){return this.occluded;}this.setOptions(a);this.attach(b);OverText.instances.push(this);if(this.options.poll){this.poll();}},toElement:function(){return this.element; +},attach:function(){var b=this.element,a=this.options,c=a.textOverride||b.get("alt")||b.get("title");if(!c){return this;}var d=this.text=new Element(a.element,{"class":a.labelClass,styles:{lineHeight:"normal",position:"absolute",cursor:"text"},html:c,events:{click:this.hide.pass(a.element=="label",this)}}).inject(b,"after"); +if(a.element=="label"){if(!b.get("id")){b.set("id","input_"+String.uniqueID());}d.set("for",b.get("id"));}if(a.wrap){this.textHolder=new Element("div.overTxtWrapper",{styles:{lineHeight:"normal",position:"relative"}}).grab(d).inject(b,"before"); +}return this.enable();},destroy:function(){this.element.eliminate(this.property);this.disable();if(this.text){this.text.destroy();}if(this.textHolder){this.textHolder.destroy(); +}return this;},disable:function(){this.element.removeEvents({focus:this.focus,blur:this.assert,change:this.assert});window.removeEvent("resize",this.reposition); +this.hide(true,true);return this;},enable:function(){this.element.addEvents({focus:this.focus,blur:this.assert,change:this.assert});window.addEvent("resize",this.reposition); +this.assert(true);this.reposition();return this;},wrap:function(){if(this.options.element=="label"){if(!this.element.get("id")){this.element.set("id","input_"+String.uniqueID()); +}this.text.set("for",this.element.get("id"));}},startPolling:function(){this.pollingPaused=false;return this.poll();},poll:function(a){if(this.poller&&!a){return this; +}if(a){clearInterval(this.poller);}else{this.poller=(function(){if(!this.pollingPaused){this.assert(true);}}).periodical(this.options.pollInterval,this); +}return this;},stopPolling:function(){this.pollingPaused=true;return this.poll(true);},focus:function(){if(this.text&&(!this.text.isDisplayed()||this.element.get("disabled"))){return this; +}return this.hide();},hide:function(c,a){if(this.text&&(this.text.isDisplayed()&&(!this.element.get("disabled")||a))){this.text.hide();this.fireEvent("textHide",[this.text,this.element]); +this.pollingPaused=true;if(!c){try{this.element.fireEvent("focus");this.element.focus();}catch(b){}}}return this;},show:function(){if(this.text&&!this.text.isDisplayed()){this.text.show(); +this.reposition();this.fireEvent("textShow",[this.text,this.element]);this.pollingPaused=false;}return this;},test:function(){return !this.element.get("value"); +},assert:function(a){return this[this.test()?"show":"hide"](a);},reposition:function(){this.assert(true);if(!this.element.isVisible()){return this.stopPolling().hide(); +}if(this.text&&this.test()){this.text.position(Object.merge(this.options.positionOptions,{relativeTo:this.element}));}return this;}});OverText.instances=[]; +Object.append(OverText,{each:function(a){return OverText.instances.each(function(c,b){if(c.element&&c.text){a.call(OverText,c,b);}});},update:function(){return OverText.each(function(a){return a.reposition(); +});},hideAll:function(){return OverText.each(function(a){return a.hide(true,true);});},showAll:function(){return OverText.each(function(a){return a.show(); +});}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(b,a){this.elements=this.subject=$$(b);this.parent(a);},compute:function(g,h,j){var c={}; +for(var d in g){var a=g[d],e=h[d],f=c[d]={};for(var b in a){f[b]=this.parent(a[b],e[b],j);}}return c;},set:function(b){for(var c in b){if(!this.elements[c]){continue; +}var a=b[c];for(var d in a){this.render(this.elements[c],d,a[d],this.options.unit);}}return this;},start:function(c){if(!this.check(c)){return this;}var h={},j={}; +for(var d in c){if(!this.elements[d]){continue;}var f=c[d],a=h[d]={},g=j[d]={};for(var b in f){var e=this.prepare(this.elements[d],b,f[b]);a[b]=e.from; +g[b]=e.to;}}return this.parent(h,j);}});Fx.Accordion=new Class({Extends:Fx.Elements,options:{fixedHeight:false,fixedWidth:false,display:0,show:false,height:true,width:false,opacity:true,alwaysHide:false,trigger:"click",initialDisplayFx:true,resetHeight:true},initialize:function(){var g=function(h){return h!=null; +};var f=Array.link(arguments,{container:Type.isElement,options:Type.isObject,togglers:g,elements:g});this.parent(f.elements,f.options);var b=this.options,e=this.togglers=$$(f.togglers); +this.previous=-1;this.internalChain=new Chain();if(b.alwaysHide){this.options.link="chain";}if(b.show||this.options.show===0){b.display=false;this.previous=b.show; +}if(b.start){b.display=false;b.show=false;}var d=this.effects={};if(b.opacity){d.opacity="fullOpacity";}if(b.width){d.width=b.fixedWidth?"fullWidth":"offsetWidth"; +}if(b.height){d.height=b.fixedHeight?"fullHeight":"scrollHeight";}for(var c=0,a=e.length;c=0?a-1:0)).chain(d);}else{d();}return this;},detach:function(b){var a=function(c){c.removeEvent(this.options.trigger,c.retrieve("accordion:display")); +}.bind(this);if(!b){this.togglers.each(a);}else{a(b);}return this;},display:function(b,c){if(!this.check(b,c)){return this;}var h={},g=this.elements,a=this.options,f=this.effects; +if(c==null){c=true;}if(typeOf(b)=="element"){b=g.indexOf(b);}if(b==this.previous&&!a.alwaysHide){return this;}if(a.resetHeight){var e=g[this.previous]; +if(e&&!this.selfHidden){for(var d in f){e.setStyle(d,e[f[d]]);}}}if((this.timer&&a.link=="chain")||(b===this.previous&&!a.alwaysHide)){return this;}this.previous=b; +this.selfHidden=false;g.each(function(l,k){h[k]={};var j;if(k!=b){j=true;}else{if(a.alwaysHide&&((l.offsetHeight>0&&a.height)||l.offsetWidth>0&&a.width)){j=true; +this.selfHidden=true;}}this.fireEvent(j?"background":"active",[this.togglers[k],l]);for(var m in f){h[k][m]=j?0:l[f[m]];}if(!c&&!j&&a.resetHeight){h[k].height="auto"; +}},this);this.internalChain.clearChain();this.internalChain.chain(function(){if(a.resetHeight&&!this.selfHidden){var i=g[b];if(i){i.setStyle("height","auto"); +}}}.bind(this));return c?this.start(h):this.set(h).internalChain.callChain();}});Fx.Move=new Class({Extends:Fx.Morph,options:{relativeTo:document.body,position:"center",edge:false,offset:{x:0,y:0}},start:function(a){var b=this.element,c=b.getStyles("top","left"); +if(c.top=="auto"||c.left=="auto"){b.setPosition(b.getPosition(b.getOffsetParent()));}return this.parent(b.position(Object.merge({},this.options,a,{returnPos:true}))); +}});Element.Properties.move={set:function(a){this.get("move").cancel().setOptions(a);return this;},get:function(){var a=this.retrieve("move");if(!a){a=new Fx.Move(this,{link:"cancel"}); +this.store("move",a);}return a;}};Element.implement({move:function(a){this.get("move").start(a);return this;}});Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical",wrapper:false,hideOverflow:true,resetHeight:false},initialize:function(b,a){b=this.element=this.subject=document.id(b); +this.parent(a);a=this.options;var d=b.retrieve("wrapper"),c=b.getStyles("margin","position","overflow");if(a.hideOverflow){c=Object.append(c,{overflow:"hidden"}); +}if(a.wrapper){d=document.id(a.wrapper).setStyles(c);}if(!d){d=new Element("div",{styles:c}).wraps(b);}b.store("wrapper",d).setStyle("margin",0);if(b.getStyle("overflow")=="visible"){b.setStyle("overflow","hidden"); +}this.now=[];this.open=true;this.wrapper=d;this.addEvent("complete",function(){this.open=(d["offset"+this.layout.capitalize()]!=0);if(this.open&&this.options.resetHeight){d.setStyle("height",""); +}},true);},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight;},horizontal:function(){this.margin="margin-left"; +this.layout="width";this.offset=this.element.offsetWidth;},set:function(a){this.element.setStyle(this.margin,a[0]);this.wrapper.setStyle(this.layout,a[1]); +return this;},compute:function(c,b,a){return[0,1].map(function(d){return Fx.compute(c[d],b[d],a);});},start:function(b,e){if(!this.check(b,e)){return this; +}this[e||this.options.mode]();var d=this.element.getStyle(this.margin).toInt(),c=this.wrapper.getStyle(this.layout).toInt(),a=[[d,c],[0,this.offset]],g=[[d,c],[-this.offset,0]],f; +switch(b){case"in":f=a;break;case"out":f=g;break;case"toggle":f=(c==0)?a:g;}return this.parent(f[0],f[1]);},slideIn:function(a){return this.start("in",a); +},slideOut:function(a){return this.start("out",a);},hide:function(a){this[a||this.options.mode]();this.open=false;return this.set([-this.offset,0]);},show:function(a){this[a||this.options.mode](); +this.open=true;return this.set([0,this.offset]);},toggle:function(a){return this.start("toggle",a);}});Element.Properties.slide={set:function(a){this.get("slide").cancel().setOptions(a); +return this;},get:function(){var a=this.retrieve("slide");if(!a){a=new Fx.Slide(this,{link:"cancel"});this.store("slide",a);}return a;}};Element.implement({slide:function(d,e){d=d||"toggle"; +var b=this.get("slide"),a;switch(d){case"hide":b.hide(e);break;case"show":b.show(e);break;case"toggle":var c=this.retrieve("slide:flag",b.open);b[c?"slideOut":"slideIn"](e); +this.store("slide:flag",!c);a=true;break;default:b.start(d,e);}if(!a){this.eliminate("slide:flag");}return this;}});(function(){Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(c,b){this.element=this.subject=document.id(c); +this.parent(b);if(typeOf(this.element)!="element"){this.element=document.id(this.element.getDocument().body);}if(this.options.wheelStops){var d=this.element,e=this.cancel.pass(false,this); +this.addEvent("start",function(){d.addEvent("mousewheel",e);},true);this.addEvent("complete",function(){d.removeEvent("mousewheel",e);},true);}},set:function(){var b=Array.flatten(arguments); +if(Browser.firefox){b=[Math.round(b[0]),Math.round(b[1])];}this.element.scrollTo(b[0],b[1]);return this;},compute:function(d,c,b){return[0,1].map(function(e){return Fx.compute(d[e],c[e],b); +});},start:function(c,d){if(!this.check(c,d)){return this;}var b=this.element.getScroll();return this.parent([b.x,b.y],[c,d]);},calculateScroll:function(g,f){var d=this.element,b=d.getScrollSize(),h=d.getScroll(),j=d.getSize(),c=this.options.offset,i={x:g,y:f}; +for(var e in i){if(!i[e]&&i[e]!==0){i[e]=h[e];}if(typeOf(i[e])!="number"){i[e]=b[e]-j[e];}i[e]+=c[e];}return[i.x,i.y];},toTop:function(){return this.start.apply(this,this.calculateScroll(false,0)); +},toLeft:function(){return this.start.apply(this,this.calculateScroll(0,false));},toRight:function(){return this.start.apply(this,this.calculateScroll("right",false)); +},toBottom:function(){return this.start.apply(this,this.calculateScroll(false,"bottom"));},toElement:function(d,e){e=e?Array.from(e):["x","y"];var c=a(this.element)?{x:0,y:0}:this.element.getScroll(); +var b=Object.map(document.id(d).getPosition(this.element),function(g,f){return e.contains(f)?g+c[f]:false;});return this.start.apply(this,this.calculateScroll(b.x,b.y)); +},toElementEdge:function(d,g,e){g=g?Array.from(g):["x","y"];d=document.id(d);var i={},f=d.getPosition(this.element),j=d.getSize(),h=this.element.getScroll(),b=this.element.getSize(),c={x:f.x+j.x,y:f.y+j.y}; +["x","y"].each(function(k){if(g.contains(k)){if(c[k]>h[k]+b[k]){i[k]=c[k]-b[k];}if(f[k]this.elements.length){e.splice(this.elements.length-1,e.length-this.elements.length); +}}var b=0;i=a=0;e.each(function(k){var j={};if(d){j.top=i-f[k].top-b;i+=f[k].height;}else{j.left=a-f[k].left;a+=f[k].width;}b=b+f[k].margin;c[k]=j;},this); +var g={};Array.clone(e).sort().each(function(j){g[j]=c[j];});this.start(g);this.currentOrder=e;return this;},rearrangeDOM:function(a){a=a||this.currentOrder; +var b=this.elements[0].getParent();var c=[];this.elements.setStyle("opacity",0);a.each(function(d){c.push(this.elements[d].inject(b).setStyles({top:0,left:0})); +},this);this.elements.setStyle("opacity",1);this.elements=$$(c);this.setDefaultOrder();return this;},getDefaultOrder:function(){return this.elements.map(function(b,a){return a; +});},getCurrentOrder:function(){return this.currentOrder;},forward:function(){return this.sort(this.getDefaultOrder());},backward:function(){return this.sort(this.getDefaultOrder().reverse()); +},reverse:function(){return this.sort(this.currentOrder.reverse());},sortByElements:function(a){return this.sort(a.map(function(b){return this.elements.indexOf(b); +},this));},swap:function(c,b){if(typeOf(c)=="element"){c=this.elements.indexOf(c);}if(typeOf(b)=="element"){b=this.elements.indexOf(b);}var a=Array.clone(this.currentOrder); +a[this.currentOrder.indexOf(c)]=b;a[this.currentOrder.indexOf(b)]=c;return this.sort(a);}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,stopPropagation:false,modifiers:{x:"left",y:"top"}},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,element:function(c){return c!=null; +}});this.element=document.id(b.element);this.document=this.element.getDocument();this.setOptions(b.options||{});var a=typeOf(this.options.handle);this.handles=((a=="array"||a=="collection")?$$(this.options.handle):document.id(this.options.handle))||this.element; +this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.ie)?"selectstart":"mousedown";if(Browser.ie&&!Drag.ondragstartFixed){document.ondragstart=Function.from(false); +Drag.ondragstartFixed=true;}this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:Function.from(false)}; +this.attach();},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this;},detach:function(){this.handles.removeEvent("mousedown",this.bound.start); +return this;},start:function(a){var j=this.options;if(a.rightClick){return;}if(j.preventDefault){a.preventDefault();}if(j.stopPropagation){a.stopPropagation(); +}this.mouse.start=a.page;this.fireEvent("beforeStart",this.element);var c=j.limit;this.limit={x:[],y:[]};var e,g;for(e in j.modifiers){if(!j.modifiers[e]){continue; +}var b=this.element.getStyle(j.modifiers[e]);if(b&&!b.match(/px$/)){if(!g){g=this.element.getCoordinates(this.element.getOffsetParent());}b=g[j.modifiers[e]]; +}if(j.style){this.value.now[e]=(b||0).toInt();}else{this.value.now[e]=this.element[j.modifiers[e]];}if(j.invert){this.value.now[e]*=-1;}this.mouse.pos[e]=a.page[e]-this.value.now[e]; +if(c&&c[e]){var d=2;while(d--){var f=c[e][d];if(f||f===0){this.limit[e][d]=(typeof f=="function")?f():f;}}}}if(typeOf(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}; +}var h={mousemove:this.bound.check,mouseup:this.bound.cancel};h[this.selection]=this.bound.eventStop;this.document.addEvents(h);},check:function(a){if(this.options.preventDefault){a.preventDefault(); +}var b=Math.round(Math.sqrt(Math.pow(a.page.x-this.mouse.start.x,2)+Math.pow(a.page.y-this.mouse.start.y,2)));if(b>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop}); +this.fireEvent("start",[this.element,a]).fireEvent("snap",this.element);}},drag:function(b){var a=this.options;if(a.preventDefault){b.preventDefault(); +}this.mouse.now=b.page;for(var c in a.modifiers){if(!a.modifiers[c]){continue;}this.value.now[c]=this.mouse.now[c]-this.mouse.pos[c];if(a.invert){this.value.now[c]*=-1; +}if(a.limit&&this.limit[c]){if((this.limit[c][1]||this.limit[c][1]===0)&&(this.value.now[c]>this.limit[c][1])){this.value.now[c]=this.limit[c][1];}else{if((this.limit[c][0]||this.limit[c][0]===0)&&(this.value.now[c]d.left&&b.xd.top);},this).getLast();if(this.overed!=a){if(this.overed){this.fireEvent("leave",[this.element,this.overed]); +}if(a){this.fireEvent("enter",[this.element,a]);}this.overed=a;}},drag:function(a){this.parent(a);if(this.options.checkDroppables&&this.droppables.length){this.checkDroppables(); +}},stop:function(a){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed,a]);this.overed=null;return this.parent(a);}});Element.implement({makeDraggable:function(a){var b=new Drag.Move(this,a); +this.store("dragger",b);return b;}});var Slider=new Class({Implements:[Events,Options],Binds:["clickedElement","draggedKnob","scrolledElement"],options:{onTick:function(a){this.setKnobPosition(a); +},initialStep:0,snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(f,a,e){this.setOptions(e);e=this.options;this.element=document.id(f); +a=this.knob=document.id(a);this.previousChange=this.previousEnd=this.step=-1;var b={},d={x:false,y:false};switch(e.mode){case"vertical":this.axis="y";this.property="top"; +this.offset="offsetHeight";break;case"horizontal":this.axis="x";this.property="left";this.offset="offsetWidth";}this.setSliderDimensions();this.setRange(e.range); +if(a.getStyle("position")=="static"){a.setStyle("position","relative");}a.setStyle(this.property,-e.offset);d[this.axis]=this.property;b[this.axis]=[-e.offset,this.full-e.offset]; +var c={snap:0,limit:b,modifiers:d,onDrag:this.draggedKnob,onStart:this.draggedKnob,onBeforeStart:(function(){this.isDragging=true;}).bind(this),onCancel:function(){this.isDragging=false; +}.bind(this),onComplete:function(){this.isDragging=false;this.draggedKnob();this.end();}.bind(this)};if(e.snap){this.setSnap(c);}this.drag=new Drag(a,c); +this.attach();if(e.initialStep!=null){this.set(e.initialStep);}},attach:function(){this.element.addEvent("mousedown",this.clickedElement);if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement); +}this.drag.attach();return this;},detach:function(){this.element.removeEvent("mousedown",this.clickedElement).removeEvent("mousewheel",this.scrolledElement); +this.drag.detach();return this;},autosize:function(){this.setSliderDimensions().setKnobPosition(this.toPosition(this.step));this.drag.options.limit[this.axis]=[-this.options.offset,this.full-this.options.offset]; +if(this.options.snap){this.setSnap();}return this;},setSnap:function(a){if(!a){a=this.drag.options;}a.grid=Math.ceil(this.stepWidth);a.limit[this.axis][1]=this.full; +return this;},setKnobPosition:function(a){if(this.options.snap){a=this.toPosition(this.step);}this.knob.setStyle(this.property,a);return this;},setSliderDimensions:function(){this.full=this.element.measure(function(){this.half=this.knob[this.offset]/2; +return this.element[this.offset]-this.knob[this.offset]+(this.options.offset*2);}.bind(this));return this;},set:function(a){if(!((this.range>0)^(a0)^(a>this.max))){a=this.max;}this.step=Math.round(a);return this.checkStep().fireEvent("tick",this.toPosition(this.step)).end();},setRange:function(a,b){this.min=Array.pick([a[0],0]); +this.max=Array.pick([a[1],this.options.steps]);this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps; +this.stepWidth=this.stepSize*this.full/Math.abs(this.range);if(a){this.set(Array.pick([b,this.step]).floor(this.min).max(this.max));}return this;},clickedElement:function(c){if(this.isDragging||c.target==this.knob){return; +}var b=this.range<0?-1:1,a=c.page[this.axis]-this.element.getPosition()[this.axis]-this.half;a=a.limit(-this.options.offset,this.full-this.options.offset); +this.step=Math.round(this.min+b*this.toStep(a));this.checkStep().fireEvent("tick",a).end();},scrolledElement:function(a){var b=(this.options.mode=="horizontal")?(a.wheel<0):(a.wheel>0); +this.set(this.step+(b?-1:1)*this.stepSize);a.stop();},draggedKnob:function(){var b=this.range<0?-1:1,a=this.drag.value.now[this.axis];a=a.limit(-this.options.offset,this.full-this.options.offset); +this.step=Math.round(this.min+b*this.toStep(a));this.checkStep();},checkStep:function(){var a=this.step;if(this.previousChange!=a){this.previousChange=a; +this.fireEvent("change",a);}return this;},end:function(){var a=this.step;if(this.previousEnd!==a){this.previousEnd=a;this.fireEvent("complete",a+"");}return this; +},toStep:function(a){var b=(a+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(b-=b%this.stepSize):b;},toPosition:function(a){return(this.full*Math.abs(this.min-a))/(this.steps*this.stepSize)-this.options.offset; +}});var Sortables=new Class({Implements:[Events,Options],options:{opacity:1,clone:false,revert:false,handle:false,dragOptions:{}},initialize:function(a,b){this.setOptions(b); +this.elements=[];this.lists=[];this.idle=true;this.addLists($$(document.id(a)||a));if(!this.options.clone){this.options.revert=false;}if(this.options.revert){this.effect=new Fx.Morph(null,Object.merge({duration:250,link:"cancel"},this.options.revert)); +}},attach:function(){this.addLists(this.lists);return this;},detach:function(){this.lists=this.removeLists(this.lists);return this;},addItems:function(){Array.flatten(arguments).each(function(a){this.elements.push(a); +var b=a.retrieve("sortables:start",function(c){this.start.call(this,c,a);}.bind(this));(this.options.handle?a.getElement(this.options.handle)||a:a).addEvent("mousedown",b); +},this);return this;},addLists:function(){Array.flatten(arguments).each(function(a){this.lists.include(a);this.addItems(a.getChildren());},this);return this; +},removeItems:function(){return $$(Array.flatten(arguments).map(function(a){this.elements.erase(a);var b=a.retrieve("sortables:start");(this.options.handle?a.getElement(this.options.handle)||a:a).removeEvent("mousedown",b); +return a;},this));},removeLists:function(){return $$(Array.flatten(arguments).map(function(a){this.lists.erase(a);this.removeItems(a.getChildren());return a; +},this));},getClone:function(b,a){if(!this.options.clone){return new Element(a.tagName).inject(document.body);}if(typeOf(this.options.clone)=="function"){return this.options.clone.call(this,b,a,this.list); +}var c=a.clone(true).setStyles({margin:0,position:"absolute",visibility:"hidden",width:a.getStyle("width")}).addEvent("mousedown",function(d){a.fireEvent("mousedown",d); +});if(c.get("html").test("radio")){c.getElements("input[type=radio]").each(function(d,e){d.set("name","clone_"+e);if(d.get("checked")){a.getElements("input[type=radio]")[e].set("checked",true); +}});}return c.inject(this.list).setPosition(a.getPosition(a.getOffsetParent()));},getDroppables:function(){var a=this.list.getChildren().erase(this.clone).erase(this.element); +if(!this.options.constrain){a.append(this.lists).erase(this.list);}return a;},insert:function(c,b){var a="inside";if(this.lists.contains(b)){this.list=b; +this.drag.droppables=this.getDroppables();}else{a=this.element.getAllPrevious().contains(b)?"before":"after";}this.element.inject(b,a);this.fireEvent("sort",[this.element,this.clone]); +},start:function(b,a){if(!this.idle||b.rightClick||["button","input","a"].contains(b.target.get("tag"))){return;}this.idle=false;this.element=a;this.opacity=a.get("opacity"); +this.list=a.getParent();this.clone=this.getClone(b,a);this.drag=new Drag.Move(this.clone,Object.merge({droppables:this.getDroppables()},this.options.dragOptions)).addEvents({onSnap:function(){b.stop(); +this.clone.setStyle("visibility","visible");this.element.set("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone]);}.bind(this),onEnter:this.insert.bind(this),onCancel:this.end.bind(this),onComplete:this.end.bind(this)}); +this.clone.inject(this.element,"before");this.drag.start(b);},end:function(){this.drag.detach();this.element.set("opacity",this.opacity);if(this.effect){var b=this.element.getStyles("width","height"),d=this.clone,c=d.computePosition(this.element.getPosition(this.clone.getOffsetParent())); +var a=function(){this.removeEvent("cancel",a);d.destroy();};this.effect.element=d;this.effect.start({top:c.top,left:c.left,width:b.width,height:b.height,opacity:0.25}).addEvent("cancel",a).chain(a); +}else{this.clone.destroy();}this.reset();},reset:function(){this.idle=true;this.fireEvent("complete",this.element);},serialize:function(){var c=Array.link(arguments,{modifier:Type.isFunction,index:function(d){return d!=null; +}});var b=this.lists.map(function(d){return d.getChildren().map(c.modifier||function(e){return e.get("id");},this);},this);var a=c.index;if(this.lists.length==1){a=0; +}return(a||a===0)&&a>=0&&a2083){this.fireEvent("error",f);}Request.JSONP.request_map["request_"+b]=function(){this.success(arguments,b);}.bind(this);var a=this.getScript(f).inject(c.injectScript); +this.fireEvent("request",[f,a]);if(c.timeout){this.timeout.delay(c.timeout,this);}return this;},getScript:function(a){if(!this.script){this.script=new Element("script",{type:"text/javascript",async:true,src:a}); +}return this.script;},success:function(b,a){if(!this.running){return;}this.clear().fireEvent("complete",b).fireEvent("success",b).callChain();},cancel:function(){if(this.running){this.clear().fireEvent("cancel"); +}return this;},isRunning:function(){return !!this.running;},clear:function(){this.running=false;if(this.script){this.script.destroy();this.script=null; +}return this;},timeout:function(){if(this.running){this.running=false;this.fireEvent("timeout",[this.script.get("src"),this.script]).fireEvent("failure").cancel(); +}return this;}});Request.JSONP.counter=0;Request.JSONP.request_map={};Request.Queue=new Class({Implements:[Options,Events],Binds:["attach","request","complete","cancel","success","failure","exception"],options:{stopOnFailure:true,autoAdvance:true,concurrent:1,requests:{}},initialize:function(a){var b; +if(a){b=a.requests;delete a.requests;}this.setOptions(a);this.requests={};this.queue=[];this.reqBinders={};if(b){this.addRequests(b);}},addRequest:function(a,b){this.requests[a]=b; +this.attach(a,b);return this;},addRequests:function(a){Object.each(a,function(c,b){this.addRequest(b,c);},this);return this;},getName:function(a){return Object.keyOf(this.requests,a); +},attach:function(a,b){if(b._groupSend){return this;}["request","complete","cancel","success","failure","exception"].each(function(c){if(!this.reqBinders[a]){this.reqBinders[a]={}; +}this.reqBinders[a][c]=function(){this["on"+c.capitalize()].apply(this,[a,b].append(arguments));}.bind(this);b.addEvent(c,this.reqBinders[a][c]);},this); +b._groupSend=b.send;b.send=function(c){this.send(a,c);return b;}.bind(this);return this;},removeRequest:function(b){var a=typeOf(b)=="object"?this.getName(b):b; +if(!a&&typeOf(a)!="string"){return this;}b=this.requests[a];if(!b){return this;}["request","complete","cancel","success","failure","exception"].each(function(c){b.removeEvent(c,this.reqBinders[a][c]); +},this);b.send=b._groupSend;delete b._groupSend;return this;},getRunning:function(){return Object.filter(this.requests,function(a){return a.running;}); +},isRunning:function(){return !!(Object.keys(this.getRunning()).length);},send:function(b,a){var c=function(){this.requests[b]._groupSend(a);this.queue.erase(c); +}.bind(this);c.name=b;if(Object.keys(this.getRunning()).length>=this.options.concurrent||(this.error&&this.options.stopOnFailure)){this.queue.push(c);}else{c(); +}return this;},hasNext:function(a){return(!a)?!!this.queue.length:!!this.queue.filter(function(b){return b.name==a;}).length;},resume:function(){this.error=false; +(this.options.concurrent-Object.keys(this.getRunning()).length).times(this.runNext,this);return this;},runNext:function(a){if(!this.queue.length){return this; +}if(!a){this.queue[0]();}else{var b;this.queue.each(function(c){if(!b&&c.name==a){b=true;c();}});}return this;},runAll:function(){this.queue.each(function(a){a(); +});return this;},clear:function(a){if(!a){this.queue.empty();}else{this.queue=this.queue.map(function(b){if(b.name!=a){return b;}else{return false;}}).filter(function(b){return b; +});}return this;},cancel:function(a){this.requests[a].cancel();return this;},onRequest:function(){this.fireEvent("request",arguments);},onComplete:function(){this.fireEvent("complete",arguments); +if(!this.queue.length){this.fireEvent("end");}},onCancel:function(){if(this.options.autoAdvance&&!this.error){this.runNext();}this.fireEvent("cancel",arguments); +},onSuccess:function(){if(this.options.autoAdvance&&!this.error){this.runNext();}this.fireEvent("success",arguments);},onFailure:function(){this.error=true; +if(!this.options.stopOnFailure&&this.options.autoAdvance){this.runNext();}this.fireEvent("failure",arguments);},onException:function(){this.error=true; +if(!this.options.stopOnFailure&&this.options.autoAdvance){this.runNext();}this.fireEvent("exception",arguments);}});Request.implement({options:{initialDelay:5000,delay:5000,limit:60000},startTimer:function(b){var a=function(){if(!this.running){this.send({data:b}); +}};this.lastDelay=this.options.initialDelay;this.timer=a.delay(this.lastDelay,this);this.completeCheck=function(c){clearTimeout(this.timer);this.lastDelay=(c)?this.options.delay:(this.lastDelay+this.options.delay).min(this.options.limit); +this.timer=a.delay(this.lastDelay,this);};return this.addEvent("complete",this.completeCheck);},stopTimer:function(){clearTimeout(this.timer);return this.removeEvent("complete",this.completeCheck); +}});var Asset={javascript:function(f,c){if(!c){c={};}var a=new Element("script",{src:f,type:"text/javascript"}),g=c.document||document,b=0,d=c.onload||c.onLoad; +var e=d?function(){if(++b==1){d.call(this);}}:function(){};delete c.onload;delete c.onLoad;delete c.document;return a.addEvents({load:e,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){e.call(this); +}}}).set(c).inject(g.head);},css:function(d,a){if(!a){a={};}var b=new Element("link",{rel:"stylesheet",media:"screen",type:"text/css",href:d});var c=a.onload||a.onLoad,e=a.document||document; +delete a.onload;delete a.onLoad;delete a.document;if(c){b.addEvent("load",c);}return b.set(a).inject(e.head);},image:function(c,b){if(!b){b={};}var d=new Image(),a=document.id(d)||new Element("img"); +["load","abort","error"].each(function(e){var g="on"+e,f="on"+e.capitalize(),h=b[g]||b[f]||function(){};delete b[f];delete b[g];d[g]=function(){if(!d){return; +}if(!a.parentNode){a.width=d.width;a.height=d.height;}d=d.onload=d.onabort=d.onerror=null;h.delay(1,a,a);a.fireEvent(e,a,1);};});d.src=a.src=c;if(d&&d.complete){d.onload.delay(1); +}return a.set(b);},images:function(c,b){c=Array.from(c);var d=function(){},a=0;b=Object.merge({onComplete:d,onProgress:d,onError:d,properties:{}},b);return new Elements(c.map(function(f,e){return Asset.image(f,Object.append(b.properties,{onload:function(){a++; +b.onProgress.call(this,a,e,f);if(a==c.length){b.onComplete();}},onerror:function(){a++;b.onError.call(this,a,e,f);if(a==c.length){b.onComplete();}}})); +}));}};(function(){var a=this.Color=new Type("Color",function(c,d){if(arguments.length>=3){d="rgb";c=Array.slice(arguments,0,3);}else{if(typeof c=="string"){if(c.match(/rgb/)){c=c.rgbToHex().hexToRgb(true); +}else{if(c.match(/hsb/)){c=c.hsbToRgb();}else{c=c.hexToRgb(true);}}}}d=d||"rgb";switch(d){case"hsb":var b=c;c=c.hsbToRgb();c.hsb=b;break;case"hex":c=c.hexToRgb(true); +break;}c.rgb=c.slice(0,3);c.hsb=c.hsb||c.rgbToHsb();c.hex=c.rgbToHex();return Object.append(c,this);});a.implement({mix:function(){var b=Array.slice(arguments); +var d=(typeOf(b.getLast())=="number")?b.pop():50;var c=this.slice();b.each(function(e){e=new a(e);for(var f=0;f<3;f++){c[f]=Math.round((c[f]/100*(100-d))+(e[f]/100*d)); +}});return new a(c,"rgb");},invert:function(){return new a(this.map(function(b){return 255-b;}));},setHue:function(b){return new a([b,this.hsb[1],this.hsb[2]],"hsb"); +},setSaturation:function(b){return new a([this.hsb[0],b,this.hsb[2]],"hsb");},setBrightness:function(b){return new a([this.hsb[0],this.hsb[1],b],"hsb"); +}});this.$RGB=function(e,d,c){return new a([e,d,c],"rgb");};this.$HSB=function(e,d,c){return new a([e,d,c],"hsb");};this.$HEX=function(b){return new a(b,"hex"); +};Array.implement({rgbToHsb:function(){var c=this[0],d=this[1],k=this[2],h=0;var j=Math.max(c,d,k),f=Math.min(c,d,k);var l=j-f;var i=j/255,g=(j!=0)?l/j:0; +if(g!=0){var e=(j-c)/l;var b=(j-d)/l;var m=(j-k)/l;if(c==j){h=m-b;}else{if(d==j){h=2+e-m;}else{h=4+b-e;}}h/=6;if(h<0){h++;}}return[Math.round(h*360),Math.round(g*100),Math.round(i*100)]; +},hsbToRgb:function(){var d=Math.round(this[2]/100*255);if(this[1]==0){return[d,d,d];}else{var b=this[0]%360;var g=b%60;var h=Math.round((this[2]*(100-this[1]))/10000*255); +var e=Math.round((this[2]*(6000-this[1]*g))/600000*255);var c=Math.round((this[2]*(6000-this[1]*(60-g)))/600000*255);switch(Math.floor(b/60)){case 0:return[d,c,h]; +case 1:return[e,d,h];case 2:return[h,d,c];case 3:return[h,e,d];case 4:return[c,h,d];case 5:return[d,h,e];}}return false;}});String.implement({rgbToHsb:function(){var b=this.match(/\d{1,3}/g); +return(b)?b.rgbToHsb():null;},hsbToRgb:function(){var b=this.match(/\d{1,3}/g);return(b)?b.hsbToRgb():null;}});})();(function(){this.Group=new Class({initialize:function(){this.instances=Array.flatten(arguments); +this.events={};this.checker={};},addEvent:function(b,a){this.checker[b]=this.checker[b]||{};this.events[b]=this.events[b]||[];if(this.events[b].contains(a)){return false; +}else{this.events[b].push(a);}this.instances.each(function(c,d){c.addEvent(b,this.check.pass([b,c,d],this));},this);return this;},check:function(c,a,b){this.checker[c][b]=true; +var d=this.instances.every(function(f,e){return this.checker[c][e]||false;},this);if(!d){return;}this.checker[c]={};this.events[c].each(function(e){e.call(this,this.instances,a); +},this);}});})();Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(b,a){this.parent(b,a);this.load();},save:function(){var a=JSON.encode(this.hash); +if(!a||a.length>4096){return false;}if(a=="{}"){this.dispose();}else{this.write(a);}return true;},load:function(){this.hash=new Hash(JSON.decode(this.read(),true)); +return this;}});Hash.each(Hash.prototype,function(b,a){if(typeof b=="function"){Hash.Cookie.implement(a,function(){var c=b.apply(this.hash,arguments);if(this.options.autoSave){this.save(); +}return c;});}});(function(){var a=this.Table=function(){this.length=0;var c=[],b=[];this.set=function(e,g){var d=c.indexOf(e);if(d==-1){var f=c.length; +c[f]=e;b[f]=g;this.length++;}else{b[d]=g;}return this;};this.get=function(e){var d=c.indexOf(e);return(d==-1)?null:b[d];};this.erase=function(e){var d=c.indexOf(e); +if(d!=-1){this.length--;c.splice(d,1);return b.splice(d,1)[0];}return null;};this.each=this.forEach=function(f,g){for(var e=0,d=this.length;e1?$$(a):a.length?document.id(a[0]):false;},setHeaders:function(a){this.set("headers",a); +return this;},setFooters:function(a){this.set("footers",a);return this;},push:function(f,c,e,a,b){if(typeOf(f)=="element"&&f.get("tag")=="tr"){f.inject(e||this.body,b); +return{tr:f,tds:f.getChildren("td")};}var d=f.map(function(i){var j=new Element(a||"td",i?i.properties:{}),h=(i?i.content:"")||i,g=typeOf(h);if(["element","array","collection","elements"].contains(g)){j.adopt(h); +}else{j.set("html",h);}return j;});return{tr:new Element("tr",c).inject(e||this.body,b).adopt(d),tds:d};}});["adopt","inject","wraps","grab","replaces","dispose"].each(function(a){HtmlTable.implement(a,function(){this.element[a].apply(this.element,arguments); +return this;});});HtmlTable=Class.refactor(HtmlTable,{options:{classZebra:"table-tr-odd",zebra:true},initialize:function(){this.previous.apply(this,arguments); +if(this.occluded){return this.occluded;}if(this.options.zebra){this.updateZebras();}},updateZebras:function(){Array.each(this.body.rows,this.zebra,this); +},setRowStyle:function(b,a){if(this.previous){this.previous(b,a);}this.zebra(b,a);},zebra:function(b,a){return b[((a%2)?"remove":"add")+"Class"](this.options.classZebra); +},push:function(){var a=this.previous.apply(this,arguments);if(this.options.zebra){this.updateZebras();}return a;}});HtmlTable=Class.refactor(HtmlTable,{options:{sortIndex:0,sortReverse:false,parsers:[],defaultParser:"string",classSortable:"table-sortable",classHeadSort:"table-th-sort",classHeadSortRev:"table-th-sort-rev",classNoSort:"table-th-nosort",classGroupHead:"table-tr-group-head",classGroup:"table-tr-group",classCellSort:"table-td-sort",classSortSpan:"table-th-sort-span",sortable:false,thSelector:"th"},initialize:function(){this.previous.apply(this,arguments); +if(this.occluded){return this.occluded;}this.sorted={index:null,dir:1};this.bound={headClick:this.headClick.bind(this)};this.sortSpans=new Elements();if(this.options.sortable){this.enableSort(); +if(this.options.sortIndex!=null){this.sort(this.options.sortIndex,this.options.sortReverse);}}},attachSorts:function(a){this.detachSorts();if(a!==false){this.element.addEvent("click:relay("+this.options.thSelector+")",this.bound.headClick); +}},detachSorts:function(){this.element.removeEvents("click:relay("+this.options.thSelector+")");},setHeaders:function(){this.previous.apply(this,arguments); +if(this.sortEnabled){this.setParsers();}},setParsers:function(){this.parsers=this.detectParsers();},detectParsers:function(){return this.head&&this.head.getElements(this.options.thSelector).flatten().map(this.detectParser,this); +},detectParser:function(a,b){if(a.hasClass(this.options.classNoSort)||a.retrieve("htmltable-parser")){return a.retrieve("htmltable-parser");}var c=new Element("div"); +c.adopt(a.childNodes).inject(a);var f=new Element("span",{"class":this.options.classSortSpan}).inject(c,"top");this.sortSpans.push(f);var g=this.options.parsers[b],e=this.body.rows,d; +switch(typeOf(g)){case"function":g={convert:g};d=true;break;case"string":g=g;d=true;break;}if(!d){HtmlTable.ParserPriority.some(function(k){var o=HtmlTable.Parsers[k],m=o.match; +if(!m){return false;}for(var n=0,l=e.length;nc){b[f].position--;}}}},setRowStyle:function(b,a){this.previous(b,a);b.cells[this.sorted.index].addClass(this.options.classCellSort); +},setGroupSort:function(b,c,a){if(b==a.value){c.removeClass(this.options.classGroupHead).addClass(this.options.classGroup);}else{c.removeClass(this.options.classGroup).addClass(this.options.classGroupHead); +}return a.value;},getParser:function(){var a=this.parsers[this.sorted.index];return typeOf(a)=="string"?HtmlTable.Parsers[a]:a;},sort:function(c,b,e){if(!this.head){return; +}if(!e){this.clearSort();this.setSortedState(c,b);this.setHeadSort(true);}var f=this.getParser();if(!f){return;}var a;if(!Browser.ie){a=this.body.getParent(); +this.body.dispose();}var d=this.parseData(f).sort(function(h,g){if(h.value===g.value){return 0;}return h.value>g.value?1:-1;});if(this.sorted.reverse==(f==HtmlTable.Parsers["input-checked"])){d.reverse(true); +}this.setRowSort(d,e);if(a){a.grab(this.body);}this.fireEvent("stateChanged");return this.fireEvent("sort",[this.body,this.sorted.index]);},parseData:function(a){return Array.map(this.body.rows,function(d,b){var c=a.convert.call(document.id(d.cells[this.sorted.index])); +return{position:b,value:c};},this);},clearSort:function(){this.setHeadSort(false);this.body.getElements("td").removeClass(this.options.classCellSort);},reSort:function(){if(this.sortEnabled){this.sort.call(this,this.sorted.index,this.sorted.reverse); +}return this;},enableSort:function(){this.element.addClass(this.options.classSortable);this.attachSorts(true);this.setParsers();this.sortEnabled=true;return this; +},disableSort:function(){this.element.removeClass(this.options.classSortable);this.attachSorts(false);this.sortSpans.each(function(a){a.destroy();});this.sortSpans.empty(); +this.sortEnabled=false;return this;}});HtmlTable.ParserPriority=["date","input-checked","input-value","float","number"];HtmlTable.Parsers={date:{match:/^\d{2}[-\/ ]\d{2}[-\/ ]\d{2,4}$/,convert:function(){var a=Date.parse(this.get("text").stripTags()); +return(typeOf(a)=="date")?a.format("db"):"";},type:"date"},"input-checked":{match:/ type="(radio|checkbox)" /,convert:function(){return this.getElement("input").checked; +}},"input-value":{match:/=b.length){a=null;}return a;},attachSelects:function(d){d=d!=null?d:true; +var g=d?"addEvents":"removeEvents";this.element[g]({mouseleave:this.bound.mouseleave,click:this.bound.activateKeyboard});this.body[g]({"click:relay(tr)":this.bound.clickRow,"contextmenu:relay(tr)":this.bound.clickRow}); +if(this.options.useKeyboard||this.keyboard){if(!this.keyboard){this.keyboard=new Keyboard();}if(!this.selectKeysDefined){this.selectKeysDefined=true;var f,e; +var c=function(i){var h=function(j){clearTimeout(f);j.preventDefault();var k=this.body.rows[this.getRowByOffset(i)];if(j.shift&&k&&this.isSelected(k)){this.deselectRow(this.focused); +this.focused=k;}else{if(k&&(!this.options.allowMultiSelect||!j.shift)){this.selectNone();}this.shiftFocus(i,j);}if(e){f=h.delay(100,this,j);}else{f=(function(){e=true; +h(j);}).delay(400);}}.bind(this);return h;}.bind(this);var b=function(){clearTimeout(f);e=false;};this.keyboard.addEvents({"keydown:shift+up":c(-1),"keydown:shift+down":c(1),"keyup:shift+up":b,"keyup:shift+down":b,"keyup:up":b,"keyup:down":b}); +var a="";if(this.options.allowMultiSelect&&this.options.shiftForMultiSelect&&this.options.useKeyboard){a=" (Shift multi-selects).";}this.keyboard.addShortcuts({"Select Previous Row":{keys:"up",shortcut:"up arrow",handler:c(-1),description:"Select the previous row in the table."+a},"Select Next Row":{keys:"down",shortcut:"down arrow",handler:c(1),description:"Select the next row in the table."+a}}); +}this.keyboard[d?"activate":"deactivate"]();}this.updateSelects();},mouseleave:function(){if(this.hovered){this.leaveRow(this.hovered);}}});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(a,b){this.element.scrollTo(a,b); +},fps:50},initialize:function(b,a){this.setOptions(a);this.element=document.id(b);this.docBody=document.id(this.element.getDocument().body);this.listener=(typeOf(this.element)!="element")?this.docBody:this.element; +this.timer=null;this.bound={attach:this.attach.bind(this),detach:this.detach.bind(this),getCoords:this.getCoords.bind(this)};},start:function(){this.listener.addEvents({mouseover:this.bound.attach,mouseleave:this.bound.detach}); +return this;},stop:function(){this.listener.removeEvents({mouseover:this.bound.attach,mouseleave:this.bound.detach});this.detach();this.timer=clearInterval(this.timer); +return this;},attach:function(){this.listener.addEvent("mousemove",this.bound.getCoords);},detach:function(){this.listener.removeEvent("mousemove",this.bound.getCoords); +this.timer=clearInterval(this.timer);},getCoords:function(a){this.page=(this.listener.get("tag")=="body")?a.client:a.page;if(!this.timer){this.timer=this.scroll.periodical(Math.round(1000/this.options.fps),this); +}},scroll:function(){var c=this.element.getSize(),a=this.element.getScroll(),h=this.element!=this.docBody?this.element.getOffsets():{x:0,y:0},d=this.element.getScrollSize(),g={x:0,y:0},e=this.options.area.top||this.options.area,b=this.options.area.bottom||this.options.area; +for(var f in this.page){if(this.page[f]<(e+h[f])&&a[f]!=0){g[f]=(this.page[f]-e-h[f])*this.options.velocity;}else{if(this.page[f]+b>(c[f]+h[f])&&a[f]+c[f]!=d[f]){g[f]=(this.page[f]-c[f]+b-h[f])*this.options.velocity; +}}g[f]=g[f].round();}if(g.y||g.x){this.fireEvent("change",[a.x+g.x,a.y+g.y]);}}});(function(){var a=function(c,b){return(c)?(typeOf(c)=="function"?c(b):b.get(c)):""; +};this.Tips=new Class({Implements:[Events,Options],options:{onShow:function(){this.tip.setStyle("display","block");},onHide:function(){this.tip.setStyle("display","none"); +},title:"title",text:function(b){return b.get("rel")||b.get("href");},showDelay:100,hideDelay:100,className:"tip-wrap",offset:{x:16,y:16},windowPadding:{x:0,y:0},fixed:false},initialize:function(){var b=Array.link(arguments,{options:Type.isObject,elements:function(c){return c!=null; +}});this.setOptions(b.options);if(b.elements){this.attach(b.elements);}this.container=new Element("div",{"class":"tip"});},toElement:function(){if(this.tip){return this.tip; +}this.tip=new Element("div",{"class":this.options.className,styles:{position:"absolute",top:0,left:0}}).adopt(new Element("div",{"class":"tip-top"}),this.container,new Element("div",{"class":"tip-bottom"})); +return this.tip;},attach:function(b){$$(b).each(function(d){var f=a(this.options.title,d),e=a(this.options.text,d);d.set("title","").store("tip:native",f).retrieve("tip:title",f); +d.retrieve("tip:text",e);this.fireEvent("attach",[d]);var c=["enter","leave"];if(!this.options.fixed){c.push("move");}c.each(function(h){var g=d.retrieve("tip:"+h); +if(!g){g=function(i){this["element"+h.capitalize()].apply(this,[i,d]);}.bind(this);}d.store("tip:"+h,g).addEvent("mouse"+h,g);},this);},this);return this; +},detach:function(b){$$(b).each(function(d){["enter","leave","move"].each(function(e){d.removeEvent("mouse"+e,d.retrieve("tip:"+e)).eliminate("tip:"+e); +});this.fireEvent("detach",[d]);if(this.options.title=="title"){var c=d.retrieve("tip:native");if(c){d.set("title",c);}}},this);return this;},elementEnter:function(c,b){clearTimeout(this.timer); +this.timer=(function(){this.container.empty();["title","text"].each(function(e){var d=b.retrieve("tip:"+e);var f=this["_"+e+"Element"]=new Element("div",{"class":"tip-"+e}).inject(this.container); +if(d){this.fill(f,d);}},this);this.show(b);this.position((this.options.fixed)?{page:b.getPosition()}:c);}).delay(this.options.showDelay,this);},elementLeave:function(c,b){clearTimeout(this.timer); +this.timer=this.hide.delay(this.options.hideDelay,this,b);this.fireForParent(c,b);},setTitle:function(b){if(this._titleElement){this._titleElement.empty(); +this.fill(this._titleElement,b);}return this;},setText:function(b){if(this._textElement){this._textElement.empty();this.fill(this._textElement,b);}return this; +},fireForParent:function(c,b){b=b.getParent();if(!b||b==document.body){return;}if(b.retrieve("tip:enter")){b.fireEvent("mouseenter",c);}else{this.fireForParent(c,b); +}},elementMove:function(c,b){this.position(c);},position:function(f){if(!this.tip){document.id(this);}var c=window.getSize(),b=window.getScroll(),g={x:this.tip.offsetWidth,y:this.tip.offsetHeight},d={x:"left",y:"top"},e={y:false,x2:false,y2:false,x:false},h={}; +for(var i in d){h[d[i]]=f.page[i]+this.options.offset[i];if(h[d[i]]<0){e[i]=true;}if((h[d[i]]+g[i]-b[i])>c[i]-this.options.windowPadding[i]){h[d[i]]=f.page[i]-this.options.offset[i]-g[i]; +e[i+"2"]=true;}}this.fireEvent("bound",e);this.tip.setStyles(h);},fill:function(b,c){if(typeof c=="string"){b.set("html",c);}else{b.adopt(c);}},show:function(b){if(!this.tip){document.id(this); +}if(!this.tip.getParent()){this.tip.inject(document.body);}this.fireEvent("show",[this.tip,b]);},hide:function(b){if(!this.tip){document.id(this);}this.fireEvent("hide",[this.tip,b]); +}});})();Locale.define("en-GB","Date",{dateOrder:["date","month","year"],shortDate:"%d/%m/%Y",shortTime:"%H:%M"}).inherit("en-US","Date"); \ No newline at end of file diff --git a/web/views/Makefile.am b/web/views/Makefile.am new file mode 100644 index 000000000..6ecec9d8b --- /dev/null +++ b/web/views/Makefile.am @@ -0,0 +1,6 @@ +AUTOMAKE_OPTIONS = gnu + +webdir = @WEB_PREFIX@/views + +dist_web_DATA = file.php \ + image.php diff --git a/web/views/Makefile.in b/web/views/Makefile.in new file mode 100644 index 000000000..2eeca05aa --- /dev/null +++ b/web/views/Makefile.in @@ -0,0 +1,453 @@ +# Makefile.in generated by automake 1.11.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software +# Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__make_dryrun = \ + { \ + am__dry=no; \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ + | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ + *) \ + for am__flg in $$MAKEFLAGS; do \ + case $$am__flg in \ + *=*|--*) ;; \ + *n*) am__dry=yes; break;; \ + esac; \ + done;; \ + esac; \ + test $$am__dry = yes; \ + } +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +subdir = web/views +DIST_COMMON = $(dist_web_DATA) $(srcdir)/Makefile.am \ + $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(webdir)" +DATA = $(dist_web_DATA) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BINDIR = @BINDIR@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CGI_PREFIX = @CGI_PREFIX@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ENABLE_MMAP = @ENABLE_MMAP@ +EXEEXT = @EXEEXT@ +EXTRA_LIBS = @EXTRA_LIBS@ +EXTRA_PERL_LIB = @EXTRA_PERL_LIB@ +FFMPEG_CFLAGS = @FFMPEG_CFLAGS@ +FFMPEG_LIBS = @FFMPEG_LIBS@ +FFMPEG_PREFIX = @FFMPEG_PREFIX@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBDIR = @LIBDIR@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIB_ARCH = @LIB_ARCH@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +MYSQL_CFLAGS = @MYSQL_CFLAGS@ +MYSQL_LIBS = @MYSQL_LIBS@ +MYSQL_PREFIX = @MYSQL_PREFIX@ +OBJEXT = @OBJEXT@ +OPT_FFMPEG = @OPT_FFMPEG@ +OPT_NETPBM = @OPT_NETPBM@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_BUILD = @PATH_BUILD@ +PATH_FFMPEG = @PATH_FFMPEG@ +PATH_NETPBM = @PATH_NETPBM@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PERL_MM_PARMS = @PERL_MM_PARMS@ +POW_LIB = @POW_LIB@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSCONFDIR = @SYSCONFDIR@ +TIME_BUILD = @TIME_BUILD@ +VERSION = @VERSION@ +WEB_GROUP = @WEB_GROUP@ +WEB_HOST = @WEB_HOST@ +WEB_PREFIX = @WEB_PREFIX@ +WEB_USER = @WEB_USER@ +ZM_CONFIG = @ZM_CONFIG@ +ZM_DB_HOST = @ZM_DB_HOST@ +ZM_DB_NAME = @ZM_DB_NAME@ +ZM_DB_PASS = @ZM_DB_PASS@ +ZM_DB_USER = @ZM_DB_USER@ +ZM_HAS_GNUTLS = @ZM_HAS_GNUTLS@ +ZM_HAS_GNUTLS_OPENSSL = @ZM_HAS_GNUTLS_OPENSSL@ +ZM_HAS_V4L = @ZM_HAS_V4L@ +ZM_HAS_V4L1 = @ZM_HAS_V4L1@ +ZM_HAS_V4L2 = @ZM_HAS_V4L2@ +ZM_LOGDIR = @ZM_LOGDIR@ +ZM_MYSQL_ENGINE = @ZM_MYSQL_ENGINE@ +ZM_PCRE = @ZM_PCRE@ +ZM_PID = @ZM_PID@ +ZM_RUNDIR = @ZM_RUNDIR@ +ZM_SSL_LIB = @ZM_SSL_LIB@ +ZM_TMPDIR = @ZM_TMPDIR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build_alias = @build_alias@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host_alias = @host_alias@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = gnu +webdir = @WEB_PREFIX@/views +dist_web_DATA = file.php \ + image.php + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu web/views/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu web/views/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-dist_webDATA: $(dist_web_DATA) + @$(NORMAL_INSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(webdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(webdir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(webdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(webdir)" || exit $$?; \ + done + +uninstall-dist_webDATA: + @$(NORMAL_UNINSTALL) + @list='$(dist_web_DATA)'; test -n "$(webdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(webdir)'; $(am__uninstall_files_from_dir) +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(DATA) +installdirs: + for dir in "$(DESTDIR)$(webdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-dist_webDATA + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-dist_webDATA + +.MAKE: install-am install-strip + +.PHONY: all all-am check check-am clean clean-generic distclean \ + distclean-generic distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am \ + install-dist_webDATA install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-dist_webDATA + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/web/views/file.php b/web/views/file.php new file mode 100644 index 000000000..772226a55 --- /dev/null +++ b/web/views/file.php @@ -0,0 +1,56 @@ + diff --git a/web/views/image.php b/web/views/image.php new file mode 100644 index 000000000..b56f34730 --- /dev/null +++ b/web/views/image.php @@ -0,0 +1,102 @@ + diff --git a/zm.conf.in b/zm.conf.in new file mode 100644 index 000000000..6a95e1b76 --- /dev/null +++ b/zm.conf.in @@ -0,0 +1,50 @@ +# ========================================================================== +# +# ZoneMinder Base Configuration, $Date$, $Revision$ +# +# ========================================================================== +# +# This file is generated by 'configure'. Care should be taken if manually +# editing this file as an changes may be overwritten by subsequent configuration +# or installations. +# + +# Current version of ZoneMinder +ZM_VERSION=@VERSION@ + +# Path to build directory, used mostly for finding DB upgrade scripts +ZM_PATH_BUILD=@PATH_BUILD@ + +# Build time, used to record when to trigger various checks +ZM_TIME_BUILD=@TIME_BUILD@ + +# Path to ZoneMinder binaries +ZM_PATH_BIN=@BINDIR@ + +# Path to ZoneMinder libraries (none at present, for future use) +ZM_PATH_LIB=@LIBDIR@ + +# Path to ZoneMinder configuration (this file only at present) +ZM_PATH_CONF=@SYSCONFDIR@ + +# Path to ZoneMinder web files +ZM_PATH_WEB=@WEB_PREFIX@ + +# Path to ZoneMinder cgi files +ZM_PATH_CGI=@CGI_PREFIX@ + +# Username and group that web daemon (httpd/apache) runs as +ZM_WEB_USER=@WEB_USER@ +ZM_WEB_GROUP=@WEB_GROUP@ + +# ZoneMinder database hostname or ip address +ZM_DB_HOST=@ZM_DB_HOST@ + +# ZoneMinder database name +ZM_DB_NAME=@ZM_DB_NAME@ + +# ZoneMinder database user +ZM_DB_USER=@ZM_DB_USER@ + +# ZoneMinder database password +ZM_DB_PASS=@ZM_DB_PASS@ diff --git a/zmconfgen.pl.in b/zmconfgen.pl.in new file mode 100644 index 000000000..5acc98daa --- /dev/null +++ b/zmconfgen.pl.in @@ -0,0 +1,190 @@ +#!/usr/bin/perl -w +# +# ========================================================================== +# +# Zone Minder Configuration Script, $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 script is used to generate initial config headers and database data. +# + +use strict; +use lib './scripts/ZoneMinder/lib'; +use ZoneMinder::ConfigData qw/:data/; + +$| = 1; + +my $config_header = "src/zm_config_defines.h"; +my $config_sql = "db/zm_create.sql"; + +generateConfigFiles(); + +exit; + +sub generateConfigFiles +{ + generateConfigHeader(); + generateConfigSQL(); +} + +sub generateConfigHeader +{ + print( "Generating '$config_header'\n" ); + open( CFG_HDR_FILE, ">$config_header" ) or die( "Can't open '$config_header' for writing" ); + print( CFG_HDR_FILE "// The file is autogenerated by zmconfgen.pl\n" ); + print( CFG_HDR_FILE "// Do not edit this file as any changes will be overwritten\n\n" ); + my $last_id = 0; + my $define_list = ""; + my $declare_list = ""; + my $assign_list = ""; + foreach my $option ( @options ) + { + next if ( !defined($option->{id}) ); + + my $opt_id = $option->{id}; + my $opt_name = $option->{name}; + my $opt_type = $option->{type}; + my $var_name = substr( lc($opt_name), 3 ); + + $define_list .= sprintf( "#define $opt_name $opt_id\n" ); + + $declare_list .= sprintf( "\t" ); + if ( $opt_type->{db_type} eq 'boolean' ) + { + $declare_list .= sprintf( "bool " ); + } + elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' ) + { + $declare_list .= sprintf( "int " ); + } + elsif ( $opt_type->{db_type} eq 'decimal' ) + { + $declare_list .= sprintf( "double " ); + } + else + { + $declare_list .= sprintf( "const char *" ); + } + $declare_list .= sprintf( $var_name.";\\\n" ); + + $assign_list .= sprintf( "\t" ); + $assign_list .= sprintf( $var_name." = " ); + if ( $opt_type->{db_type} eq 'boolean' ) + { + $assign_list .= sprintf( "(bool)" ); + } + elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' ) + { + $assign_list .= sprintf( "(int)" ); + } + elsif ( $opt_type->{db_type} eq 'decimal' ) + { + $assign_list .= sprintf( "(double) " ); + } + else + { + $assign_list .= sprintf( "(const char *)" ); + } + $assign_list .= sprintf( "config.Item( ".$opt_name." );\\\n" ); + + $last_id = $option->{id}; + } + print( CFG_HDR_FILE $define_list."\n\n" ); + print( CFG_HDR_FILE "#define ZM_MAX_CFG_ID $last_id\n\n" ); + print( CFG_HDR_FILE "#define ZM_CFG_DECLARE_LIST \\\n" ); + print( CFG_HDR_FILE $declare_list."\n\n" ); + print( CFG_HDR_FILE "#define ZM_CFG_ASSIGN_LIST \\\n" ); + print( CFG_HDR_FILE $assign_list."\n\n" ); + close( CFG_HDR_FILE ); +} + +sub generateConfigSQL +{ + print( "Updating '$config_sql'\n" ); + my $config_sql_temp = $config_sql.".temp"; + open( CFG_SQL_FILE, "<$config_sql" ) or die( "Can't open '$config_sql' for reading" ); + open( CFG_TEMP_SQL_FILE, ">$config_sql_temp" ) or die( "Can't open '$config_sql_temp' for writing" ); + while ( my $line = ) + { + last if ( $line =~ /^-- This section is autogenerated/ ); + print( CFG_TEMP_SQL_FILE $line ); + } + close( CFG_SQL_FILE ); + + print( CFG_TEMP_SQL_FILE "-- This section is autogenerated by zmconfgen.pl\n" ); + print( CFG_TEMP_SQL_FILE "-- Do not edit this file as any changes will be overwritten\n" ); + print( CFG_TEMP_SQL_FILE "--\n\n" ); + print( CFG_TEMP_SQL_FILE "delete from Config;\n\n" ); + foreach my $option ( @options ) + { + #print( $option->{name}."\n" ) if ( !$option->{category} ); + $option->{db_type} = $option->{type}->{db_type}; + $option->{db_hint} = $option->{type}->{hint}; + $option->{db_pattern} = $option->{type}->{pattern}; + $option->{db_format} = $option->{type}->{format}; + if ( $option->{db_type} eq "boolean" ) + { + $option->{db_value} = ($option->{value} eq "yes")?"1":"0"; + } + else + { + $option->{db_value} = $option->{value}; + } + if ( $option->{name} eq "ZM_DYN_CURR_VERSION" || $option->{name} eq "ZM_DYN_DB_VERSION" ) + { + $option->{db_value} = '@VERSION@'; + } + if ( my $requires = $option->{requires} ) + { + $option->{db_requires} = join( ";", map { my $value = $_->{value}; $value = ($value eq "yes")?1:0 if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ); ( "$_->{name}=$value" ) } @$requires ); + } + else + { + $option->{db_requires} = ""; + } + printf( CFG_TEMP_SQL_FILE + "insert into Config set Id = %d, Name = '%s', Value = '%s', Type = '%s', DefaultValue = '%s', Hint = '%s', Pattern = '%s', Format = '%s', Prompt = '%s', Help = '%s', Category = '%s', Readonly = '%s', Requires = '%s';\n", + $option->{id}, + $option->{name}, + addSlashes($option->{db_value}), + $option->{db_type}, + addSlashes($option->{default}), + addSlashes($option->{db_hint}), + addSlashes($option->{db_pattern}), + addSlashes($option->{db_format}), + addSlashes($option->{description}), + addSlashes($option->{help}), + $option->{category}, + $option->{readonly}?1:0, + $option->{db_requires} + ); + } + print( CFG_TEMP_SQL_FILE "\n" ); + close( CFG_TEMP_SQL_FILE ); + + rename( $config_sql_temp, $config_sql ) or die( "Can't rename '$config_sql_temp' to '$config_sql': $!" ); +} + +sub addSlashes +{ + my $string = shift; + return( "" ) if ( !defined($string) ); + $string =~ s|(['"])|\\$1|g; + return( $string ); +}

Bp;Q{Be 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%0DmR% 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